Volatile IEnlistmentNotification and TransactionScope.AsyncF
本文关键字:AsyncF TransactionScope and IEnlistmentNotification Volatile | 更新日期: 2023-09-27 18:32:55
除了.NET 4.5.1之外,TransactionScope上还有一个新选项,可以使用异步流。这允许编写以下客户端代码
using(var txt = new TransactionScope(..., TransactionScopeAsyncFlowOption.Enabled)
{
await sender.SendAsync();
}
目前为止,一切都好。但是当我需要实现一个易失性的IEnlistmentNotice时,我正在努力做到这一点。让我们想象一下以下场景,假设:我的底层基础架构从下到上完全异步
public class MessageSender : ISendMessages
{
public async Task SendAsync(TransportMessage message, SendOptions options)
{
await sender.SendAsync(message);
}
}
因此,我想要实现的是引入一个易失性的IEnlistmentNotification,如下所示:
internal class SendResourceManager : IEnlistmentNotification
{
private readonly Func<Task> onCommit;
public SendResourceManager(Func<Task> 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) }));
}
}
注意:当然,此代码无法编译。这将要求我声明提交方法异步无效。这是令人敬畏的。
所以我的问题是:如何编写可以在内部等待异步操作的登记?
只要EnlistVolatile
不是繁重的 CPU 密集型耗时操作,您就可以使用 Task.FromResult
在 EnlistVolatile
上创建一个基于 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) }));
}
}
可以在调用堆栈中等待更高的位置:
MessageSender sender = new MessageSender();
await sender.SendAsync(message, options);