获取TransactionScope以使用async / await

时间:2012-11-24 16:47:09

标签: c# transactionscope async-await

我正在尝试将async / await集成到我们的服务总线中。 我根据此示例http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx实施了SingleThreadSynchronizationContext

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

TransactionScope似乎与async / await不太匹配,当然因为它使用ThreadStaticAttribute将内容存储在线程中。我得到了这个例外:

  

“TransactionScope嵌套错误。”。

我尝试在排队任务之前保存TransactionScope数据并在运行之前将其恢复,但似乎没有改变任何事情。并且TransactionScope代码很乱,所以很难理解那里发生了什么。

有没有办法让它发挥作用?是否有TransactionScope的替代方案?

3 个答案:

答案 0 :(得分:154)

在.NET Framework 4.5.1中,有一组new constructors for TransactionScope采用TransactionScopeAsyncFlowOption参数。

根据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();
}

答案 1 :(得分:7)

回答迟到但我遇到了与MVC4相同的问题,我通过右键单击项目将属性从4.5更新到4.5.1。选择应用程序选项卡将目标框架更改为4.5.1并使用事务如下。

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

答案 2 :(得分: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/