在线程之间共享事务范围

时间:2010-11-17 11:41:55

标签: c# .net multithreading transactions transactionscope

我有一个班级做一些交易代码 让我们假设:

class Worker
{
    public void doWork()
    {
        //I do not want to create a new transaction. Instead, i want to use the environmenttransaction used by the caller of this method
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))             {
            workItem1();
            workItem2();
            workItem3();
            scope.Complete();
        }
    }

现在我有一些执行此代码的线程:

Worker worker = new Worker();
using (TransactionScope transaction = new TransactionScope())
{
    Thread Thread1 = new Thread(new ThreadStart(worker.doWork));
    Thread1.Start();
    Thread Thread2 = new Thread(new ThreadStart(worker.doWork));
    Thread2.Start();
    Thread Thread3 = new Thread(new ThreadStart(worker.doWork));
    Thread3.Start();

    Thread.Sleep(10000); //this should be enough to all the workers finish their job

    transaction.Complete();
}  

每个线程都在创建自己的事务。我如何在所有线程之间共享相同的事务?

3 个答案:

答案 0 :(得分:6)

您可以查看DependentTransaction类,它对多个线程的事务很有用。请参阅documentation

答案 1 :(得分:1)

您拥有的代码将创建竞争条件。在线程完成之前,您几乎会立即调用scope.complete。

然而,即使每个工作者都创建了一个事务范围,如果创建了一个新事务范围,这些实际上也会被.Net嵌套到顶级事务范围。

如果您想要嵌套分层事务,那么您可能希望使用ScopeOption.RequiresNew创建新范围。但这是一个真实问题的答案,这就是你想要这样做的原因。交易固有地意味着您的工作在某种程度上是顺序的或关键的,以某种顺序发生。如果你可以并行完成工作,那么尽可能尝试在单独的事务中进行,将范围限制在尽可能短的时间内,以防止锁定等。

答案 2 :(得分:-3)

您的代码存在的问题是您在打电话之前没有等待所有线程完成工作:

            transaction.Complete();

因此,在多线程事务作为原子事务完成之前,任何线程都可以调用此方法。您可能需要使用Semaphore类来避免冲突。

另外,如果您的环境允许,我会考虑使用PLinq。