使用TransactionScope和Tasks时出现问题,无法使用。

4

我正在尝试跨两个不同的SQL Server实例使用TransactionScope(该事务被升级为MSDTC)。在非异步任务下,我已经成功地使其工作,但在使用异步任务时无法使事务回滚。

我已将连接到服务器和更新语句都隐藏了,但请放心,它们都连接并执行SQL没有问题。我有意将方法runTwo()中的SQL设置为失败并引发异常。

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

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();

            }
        }
1个回答

4
这是:

Task.WhenAll(tasks);

如果您的问题是:当Task.WhenAll返回一个可等待对象时,它不会在方法调用上进行阻塞。由于您正在使用控制台应用程序,因此无法进行等待,您需要改用Task.WaitAll,该方法将明确地阻塞,直到两个请求完成,并通过AggregateException传播任何异常。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接