我正在看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服务刚刚作为服务引用添加到类库中,它生成Async方法包装器。
在Adam和Udi评论之后编辑。
看起来这个问题与NServiceBus无关,它更多地与控制台应用程序如何处理抛出异常的异步方法有关。请看线程
Catch unhandled exceptions from async
Stephen Cleary写了这个
http://nuget.org/packages/Nito.AsyncEx
它可以帮助您滚动自己的SynchronisationContext来处理捕获异常。所以上面的WCF调用包含了这样......
var league = AsyncContext.Run(() => service.UpdateAsync(leagueDto));
当抛出异常时,它会在该上下文中被捕获,并且控制台应用程序不再关闭。
答案 0 :(得分:3)
当您将其称为异步时,异常发生在与处理消息的线程不同的线程上。出于这个原因,NServiceBus无法知道哪个消息是导致该异常的消息,因此它无法回滚任何内容。
使用NServiceBus时,您的整体架构已经异步 - 实际上不需要异步执行这些WCF调用。