除了.NET 4.5.1有在其上使得能够使用异步流的TransactionScope一个新的选择。这使得写出下列客户端code
Apart from .NET 4.5.1 there is a new option on the TransactionScope which enables to use async flow. This allows to write the following client code
using(var txt = new TransactionScope(..., TransactionScopeAsyncFlowOption.Enabled)
{
await sender.SendAsync();
}
到目前为止好。但是,当我需要实现挥发性IEnlistmentNotification我努力做到这一点。让我们想象一下下面的情况下,假设:我的基础架构是从底部完全异步顶部
So far so good. But when I need to implement a volatile IEnlistmentNotification I'm struggling to do that. Let's imagine the following scenario, assumption: My underlying infrastructure is completely async from bottom to top
public class MessageSender : ISendMessages
{
public async Task SendAsync(TransportMessage message, SendOptions options)
{
await sender.SendAsync(message);
}
}
所以,我想实现的是引入一种挥发性IEnlistmentNotification是这样的:
So what I want to achieve is to introduce a volatile IEnlistmentNotification like this:
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) }));
}
}
注:当然这个code不能编译。这需要我申报commit方法异步无效。这是aweful。
Note: Of course this code doesn't compile. It would require me to declare the commit method async void. Which is aweful.
我的问题是:我如何写一个征兵它可以在内部等待异步操作
So my question is: How can I write an enlistment which can internally await an asynchronous operation?
推荐答案
只要 EnlistVolatile
是不是一个沉重的CPU势必耗时的操作,您可以创建一个薄工作
根据包装过 EnlistVolatile
使用的 Task.FromResult
:
As long as EnlistVolatile
isn't a heavy CPU bound time consuming operation, you can create a thin Task
based wrapper over EnlistVolatile
using Task.FromResult
:
public static class TranscationExtensions
{
public static Task EnlistVolatileAsync(this Transaction transaction,
IEnlistmentNotification
enlistmentNotification,
EnlistmentOptions enlistmentOptions)
{
return Task.FromResult(transaction.EnlistVolatile
(enlistmentNotification,
enlistmentOptions));
}
}
,然后使用它的方法中:
and then consume it inside your method:
public class MessageSender : ISendMessages
{
public Task SendAsync(TransportMessage message, SendOptions options)
{
return Transaction.Current.EnlistVolatileAsync
(new SendResourceManager(async () =>
{ await sender.SendAsync(message) }));
}
}
您也可以在调用堆栈来等待更高的:
which can be awaited higher in your callstack:
MessageSender sender = new MessageSender();
await sender.SendAsync(message, options);
相关推荐
最新文章