2012-11-24 105 views
97

我试图将async/await集成到我们的服务总线中。 我实施了一个SingleThreadSynchronizationContext基于此示例http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx获取TransactionScope以使用异步/等待

它工作正常,除了一件事:TransactionScope。我正在等待TransactionScope内部的内容,并打破TransactionScope

TransactionScope似乎并不发挥好与async/await,肯定是因为它存储在使用ThreadStaticAttribute线程的东西。我得到这个例外:

“TransactionScope嵌套不正确。”。

我试图在排队任务之前保存TransactionScope数据,并在运行之前将其恢复,但似乎并未改变任何事情。并且TransactionScope代码是一团糟,所以很难理解那里正在发生的事情。

有没有办法让它工作?是否有一些替代TransactionScope

+0

这是一个非常简单的代码来重现一个TransactionScope错误http://pastebin.com/Eh1dxG4a除了这里的异常事务中止 – Yann

+0

你能NIT只是使用普通的SQL事务?或者你跨越多个资源? –

+0

我跨越多个资源 – Yann

回答

6

可以使用DependentTransaction通过Transaction.DependentClone()方法创建:

static void Main(string[] args) 
{ 
    // ... 

    for (int i = 0; i < 10; i++) 
    { 

    var dtx = Transaction.Current.DependentClone(
     DependentCloneOption.BlockCommitUntilComplete); 

    tasks[i] = TestStuff(dtx); 
    } 

    //... 
} 


static async Task TestStuff(DependentTransaction dtx) 
{ 
    using (var ts = new TransactionScope(dtx)) 
    { 
     // do transactional stuff 

     ts.Complete(); 
    } 
    dtx.Complete(); 
} 

Managing Concurrency with DependentTransaction

http://adamprescott.net/2012/10/04/transactionscope-in-multi-threaded-applications/

+1

Adam Prescott的示例子任务未标记为异步。如果用类似'await Task.Delay(500)'的东西替换“做事务性的东西”,这种模式也会失败,'TransactionScope嵌套错误',因为最上面的TransactionScope(在上面的例子中没有显示)完成。用'Task.Wait()'替换'await',它可以工作,但是你失去了'async'的好处。 – mdisibio

+0

这是一个解决问题的更难的方法。 TransactionScope将隐藏所有管道。 – Eniola

138

在.NET框架4.5.1,有可能采取TransactionScopeAsyncFlowOption一套new constructors for TransactionScope参数。

根据MSDN,它支持跨线程延续的事务流。

我的理解是,它的目的是让你写这样的代码:我迟到了一个答案

// transaction scope 
using (var scope = new TransactionScope(... , 
    TransactionScopeAsyncFlowOption.Enabled)) 
{ 
    // connection 
    using (var connection = new SqlConnection(_connectionString)) 
    { 
    // open connection asynchronously 
    await connection.OpenAsync(); 

    using (var command = connection.CreateCommand()) 
    { 
     command.CommandText = ...; 

     // run command asynchronously 
     using (var dataReader = await command.ExecuteReaderAsync()) 
     { 
     while (dataReader.Read()) 
     { 
      ... 
     } 
     } 
    } 
    } 
    scope.Complete(); 
} 
9

位,但在和MVC4了同样的问题,我在我的项目更新,从4.5到4.5 .1通过右键单击项目转到属性。选择应用程序选项卡更改目标框架到4.5.1并使用事务如下。

using (AccountServiceClient client = new AccountServiceClient()) 
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 
{ 
}