3

我正在查看 NServiceBus v3.3.0.0,在我们的 MessageHandler 中它调用外部 WCF 服务。

如果 WCF 服务被同步调用并且该服务抛出异常,NServiceBus 会完美处理它并根据配置重试该过程。

但是,如果异步调用 WCF 服务并引发异常,则订阅者进程将崩溃。

因此,例如,如果 service.Update 抛出,这可以很好地处理异常

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

但如果对 service.UpdateAsync 的调用引发异常,则进程崩溃

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

WCF 服务只是作为服务引用添加到类库中,它生成异步方法包装器。

在 Adam 和 Udi 评论之后进行编辑。

看起来这个问题与 NServiceBus 无关,它更多地与控制台应用程序如何处理抛出异常的异步方法有关。请看线程

从异步中捕获未处理的异常

斯蒂芬克利里写了这个

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

这可以帮助您滚动自己的 SynchronisationContext 来处理捕获异常。所以上面的 WCF 调用是这样包装的......

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

当抛出异常时,它会在该上下文中被捕获,并且控制台应用程序不再关闭。

4

1 回答 1

3

当您将其称为异步时,异常发生在与处理消息的线程不同的线程上。出于这个原因,NServiceBus 无法知道哪个消息是导致该异常的消息,因此它无法回滚任何内容。

使用 NServiceBus 时,您的整体架构已经是异步的——实际上没有任何需要异步执行这些 WCF 调用。

于 2012-11-28T08:07:31.737 回答