create an async method that wraps subscribe and publish on a bus

.net-4.5, asynchronous, c#, c#-5.0, publish-subscribe

Solution

You can use `TaskCompletionSource<T>` to wrap anything into an `await`-compatible method.

public static Task<TResult> Request<TRequest, TResult>(this IBus bus, TRequest request)
{
  var tcs = new TaskCompletionSource<TResult>();
  var id = Guid.NewGuid();
  bus.Subscribe<TResult>(id, result =>
  {
    bus.Unsubscribe<TResult>(id);
    tcs.TrySetResult(result);
  });
  bus.Publish(request);
  return tcs.Task;
}

Note, however, that you should ensure that the task is completed. If there's any chance that the bus won't respond to the request, you should have a timer or something that faults the `TaskCompletionSource`.

Problem

I have a kind of bus that implements this interface: ``` public interface IBus { void Publish<T>(T t); void Subscribe<T>(Guid subscriptionId, Action<T> action); void Unsubscribe<T>(Guid subscriptionId); } ``` Here is an example on how I use it: ``` public void PrintName() { IBus bus = new Bus(); var id = Guid.NewGuid(); bus.Subscribe<ReplyUserName>(id, replyUserName => { bus.Unsubscribe<ReplyUserName>(id); Console.WriteLine(replyUserName.UserName); }); Bus.Publish(new RequestUserName()); } ``` And here are the RequestUserName and ReplyUserName classes: ``` public class RequestUserName {} public class ReplyUserName { public string UserName { get; set; } } ``` However I would like to write an extension method that would wrap this with async: ``` public static class BusExtension { public static async Task<TResult> Request<TRequest, TResult>(this IBus bus, TRequest request) { // TODO... } } ``` So that I will be able to write the previous code in such a way: ``` public async void PrintName() { IBus bus = new Bus(); var replyUserName = await bus.Request<RequestUserName, ReplyUserName>(new RequestUserName()); Console.WriteLine(replyUserName.UserName); } ``` what should I write instead of the TODO?

Original source