无法将 TransactionScope 与任务一起使用

Unable to use TransactionScope with Tasks

我试图在对不同 SQL 服务器实例的两个查询中使用 TransactionScope(事务被提升为 MSDTC)。我让它在不使用 Tasks 的情况下同步工作,但在异步使用 Tasks 时无法使事务回滚。

我已经隐藏了服务器的连接字符串和更新语句,但请放心,它们都可以毫无问题地连接和执行 SQL。我故意将方法 runTwo() 中的 SQL 设置为失败并引发异常。

我正在使用 .Net 4.5.2,其中包括枚举 TransactionScopeAsyncFlowOption.Enabled(在 TransactionScope 构造函数中),我认为它应该处理跨线程的事务,但我无法让它工作。

static void Main()
        {
            List<Task> tasks = new List<Task>();
            using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
            {
                try
                {
                    tasks.Add(Task.Run(() => runOne()));
                    tasks.Add(Task.Run(() => runTwo()));

                    Task.WhenAll(tasks);

                    //Complete the scope
                    scope.Complete();
                }
                catch (Exception)
                {
                    Transaction.Current.Rollback();
                }
            }
            Console.ReadLine();
        }

        private static void runOne()
        {
            //Get the base SQL connection
            using (SqlConnection conn = new SqlConnection("Data Source=SERVER1....."))
            {
                conn.Open();

                SqlCommand command1 = new SqlCommand
                {
                    CommandText = "Update .. Complete Successfully",
                    CommandType = CommandType.Text,
                    Connection = conn
                };

                command1.ExecuteNonQuery();
            }
        }

        private static void runTwo()
        {
            using (
                SqlConnection conn =
                    new SqlConnection("Data Source=SERVER2...")
                )
            {
                conn.Open();

                SqlCommand command2 = new SqlCommand
                {
                    CommandText = "Update .... Raises Exception",
                    CommandType = CommandType.Text,
                    Connection = conn
                };

                //Execute the command
                command2.ExecuteNonQuery();

            }
        }

这个:

Task.WhenAll(tasks);

是你的问题。 Task.WhenAll returns 一个 awaitable,它不会 block 方法调用。由于您使用的是无法等待的控制台应用程序,因此您必须推迟使用 Task.WaitAll ,这将明确阻止直到两个请求都完成,并将通过 AggregateException [=15= 传播任何异常]

try
{
    Task.WaitAll(new[] { Task.Run(() => runOne()), 
                         Task.Run(() => runTwo()) });
    scope.Complete();
}