挥发性IEnlistmentNotification和TransactionScope.AsyncFlowEnabled =真挥发性、IEnlistmentNotification、AsyncFlow

由网友(故作优雅、)分享简介:除了.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...

除了.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);
阅读全文

相关推荐

最新文章