3

I'm looking at NServiceBus v3.3.0.0, in our MessageHandler it calls an external WCF service.

If the WCF service is called synchronously and that service throws an exception, NServiceBus handles it perfectly and retries the process as per configuration.

But, if the WCF service is called asynchronously and an exception is thrown then the subscriber process crashes.

So, for example, this handles the exception fine if service.Update throws

   public class LeagueMessageHandler : IHandleMessages<LeagueMessage>
   {
       public void Handle(LeagueMessage message)
       {
           var service = new LeagueService.LeagueContractClient();
           var league = service.Update(leagueDto);
       }
   }

but if the call to service.UpdateAsync throws an exception then the process crashes

   public class LeagueMessageHandler : IHandleMessages<LeagueMessage>
   {
       public async void Handle(LeagueMessage message)
       {
           var service = new LeagueService.LeagueContractClient();
           var league = await service.UpdateAsync(leagueDto);
       }
   }

The WCF service is just added as a Service Reference to the class library, it generates the Async method wrappers.

Edit after Adam and Udi comments.

It looks like the issue is unrelated to NServiceBus it's more to do with how console applications handle async methods throwing exceptions. Please see thread

Catch unhandled exceptions from async

Stephen Cleary has written this

http://nuget.org/packages/Nito.AsyncEx

which helps you roll your own SynchronisationContext which handles catching the exception. So the WCF call above is wrapped such...

        var league = AsyncContext.Run(() => service.UpdateAsync(leagueDto));

when the exception gets thrown it is caught within that context and the console app no longer closes.

Community
  • 1
  • 1
applefish
  • 178
  • 1
  • 6
  • Do you get some kind of error prior to the crash? – Adam Fyles Nov 28 '12 at 01:15
  • Thanks Adam. For completeness the exception was System.ServiceModel.FaultException: Value cannot be null. Which led me to the other SO thread about console app issues with async exceptions. – applefish Nov 28 '12 at 08:55

1 Answers1

3

When you call it async, the exception happens on a different thread than the one that is processing the message. For that reason, there's no way for NServiceBus to know which message was the one to cause that exception, so it can't roll anything back.

When using NServiceBus, your overall architecture is already asynchronous - there really isn't any need to perform these WCF calls asynchronously.

Udi Dahan
  • 11,932
  • 1
  • 27
  • 35
  • I think the issue is unrelated to NServiceBus it's more to do with how console apps handle async calls throwing exceptions. – applefish Nov 28 '12 at 08:34
  • Thanks for your response Udi. If the call to the WCF service is synchronous does that block that thread? I'm being cautious as I know that particular service can sometimes be slow to respond. – applefish Nov 28 '12 at 08:52
  • If the WCF call is synchronous, yes, it will block the thread, but that's why you have a multithreaded process. – Udi Dahan Nov 28 '12 at 09:38
  • @UdiDahan from what i understand of async await, there are good reasons to use it (even in an already threaded application). The reason is that when you call await on an action which is going to a remote system the thread is dehydrated and returned to the thread pool until the remote system responds. This means you have less concurrent threads running. see http://stackoverflow.com/q/20851843/1070291 – undefined Feb 23 '14 at 22:17
  • @LukeMcGregor NServiceBus can't/won't release the thread in this case because it needs to resolve the ambient message transaction, so you're not really getting any performance improvements or reduction in resource utilization with async/await here. – Udi Dahan Feb 25 '14 at 17:05
  • @UdiDahan is it really not possible to marshal the transaction onto the new thread in the same way ASP.NET does with its context? It would be good to use async APIs to get the most out of our resource constrained cloud servers and we have a lot of network I/O initiated and waited upon in our NSB handlers. – Josh Gallagher Jan 14 '15 at 12:25
  • @JoshGallagher We have started looking at how we can do more in this area. Keep an eye out for that. – Udi Dahan Jan 15 '15 at 16:34