易失性IEnlistmentNotification和TransactionScope.AsyncFlowEnabled = true

除了.NET 4.5.1之外,TransactionScope上还有一个新选项,可以使用异步流。 这允许编写以下客户端代码

using(var txt = new TransactionScope(..., TransactionScopeAsyncFlowOption.Enabled) { await sender.SendAsync(); } 

到现在为止还挺好。 但是当我需要实现一个易变的IEnlistmentNotification时,我正在努力做到这一点。 让我们假设以下场景,假设:我的底层基础架构从下到上完全异步

 public class MessageSender : ISendMessages { public async Task SendAsync(TransportMessage message, SendOptions options) { await sender.SendAsync(message); } } 

所以我想要实现的是引入像这样的易失性IEnlistmentNotification:

 internal class SendResourceManager : IEnlistmentNotification { private readonly Func onCommit; public SendResourceManager(Func onCommit) { this.onCommit = onCommit; } public void Prepare(PreparingEnlistment preparingEnlistment) { preparingEnlistment.Prepared(); } public void Commit(Enlistment enlistment) { await this.onCommit(); enlistment.Done(); } public void Rollback(Enlistment enlistment) { enlistment.Done(); } public void InDoubt(Enlistment enlistment) { enlistment.Done(); } } 

和新的发件人

 public class MessageSender : ISendMessages { public async Task SendAsync(TransportMessage message, SendOptions options) { // Dirty: Let's assume Transaction.Current is never null Transaction.Current.EnlistVolatile(new SendResourceManager(async () => { await sender.SendAsync(message) })); } } 

注意:当然这段代码不能编译。 它需要我声明提交方法async void。 这是令人敬畏的。

所以我的问题是:我如何编写一个可以在内部等待异步操作的登记?

只要EnlistVolatile不是繁重的CPU绑定耗时操作,您就可以使用Task.FromResultEnlistVolatile创建基于Task的精简包装器:

 public static class TranscationExtensions { public static Task EnlistVolatileAsync(this Transaction transaction, IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions) { return Task.FromResult(transaction.EnlistVolatile (enlistmentNotification, enlistmentOptions)); } } 

然后在你的方法中使用它:

 public class MessageSender : ISendMessages { public Task SendAsync(TransportMessage message, SendOptions options) { return Transaction.Current.EnlistVolatileAsync (new SendResourceManager(async () => { await sender.SendAsync(message) })); } } 

在你的callstack中可以等待更高:

 MessageSender sender = new MessageSender(); await sender.SendAsync(message, options);