With
NServiceBus sometimes you do not want to allow a web request to complete until you have received some response from your message handler. For example, suppose you have defined the following message handler that returns a response code on success:
public class TestMessageHandler :
IHandleMessages<TestMessage>
{
public IBus Bus { get; set; }
public void Handle(TestMessage message)
{
//Do something interesting...
Bus.Return(0);
}
}
This is a perfect scenario for using the asynchronous page API. It allows you to execute a potentially long-running operation on a separate thread outside of the IIS thread pool. While this thread is executing, the original request thread is returned to the thread pool. As a result, the asynchronous page API is great for I/O bound operations, since you keep threads in the thread pool ready to service requests and the new thread spends most of its time blocked on I/O. NServiceBus supports the asynchronous page API out of the box:
Bus.Send(new TestMessage()).RegisterWebCallback(callback, state);
Unfortunately, RegisterWebCallback does not work with ASP.NET MVC. If you are using ASP.NET MVC, you can use
AsyncController, which was introduced in ASP.NET MVC 2. The following code illustrates how you might use AsyncController to wait for a response the message handler:
public class TestController : AsyncController
{
private IBus bus;
public TestController(IBus bus)
{
this.bus = bus;
}
public void IndexAsync()
{
AsyncManager.OutstandingOperations.Increment();
bus.Send(new TestMessage()).Register(Callback);
}
public ActionResult IndexCompleted()
{
return View();
}
private void Callback(int responseCode)
{
AsyncManager.OutstandingOperations.Decrement();
}
}
As you can see, the AsyncController API is a little awkward (though it is an improvement over the asynchronous page API, in my opinion), but it is a small price to pay for scalability.