根据这篇MSDN文章,你应该能够使用单个根事务在多线程进程中运行每个线程。
我基于那篇文章创建了一个示例程序,在其中期望回滚事务(
此外,我尝试了
其次,我认为
最后,我的问题 :) 为什么这个方法不起作用?我做错了什么?将多个线程包装在单个事务中真的不可能吗?
我基于那篇文章创建了一个示例程序,在其中期望回滚事务(
foreach
循环中的bool[] results
应全部为false
)。不幸的是,实际情况并非如此,结果是不可预测的(多次运行示例程序会看到数组中的任何bool
值的组合)。此外,我尝试了
DependentCloneOption.BlockCommitUntilComplete
和DependentCloneOption.RollbackIfNotComplete
,但都没有产生预期结果。其次,我认为
ThreadPool.QueueUserWorkItem
代码最丑陋,最好使用Parallel.ForEach
来替代它。最后,我的问题 :) 为什么这个方法不起作用?我做错了什么?将多个线程包装在单个事务中真的不可能吗?
namespace Playing
{
class Program
{
static bool[] results = new bool[] { false, false, false };
static void Main(string[] args)
{
try
{
using (var outer = new TransactionScope(
TransactionScopeOption.Required))
{
for (var i = 0; i < 3; i++ )
{
ThreadPool.QueueUserWorkItem(WorkerItem,
new Tuple<int, object>(
i, Transaction.Current.DependentClone(
DependentCloneOption.BlockCommitUntilComplete)));
}
outer.Complete();
}
}
catch { /* Suppress exceptions */ }
// Expect all to be false
foreach (var r in results)
Console.WriteLine(r);
}
private static void WorkerItem(object state)
{
var tup = (Tuple<int, object>)state;
var i = tup.Item1;
var dependent = (DependentTransaction)tup.Item2;
using (var inner = new TransactionScope(dependent))
{
// Intentionally throw exception to force roll-back
if (i == 2)
throw new Exception();
results[i] = true;
inner.Complete();
}
dependent.Complete();
}
}
}