gpt4 book ai didi

c# - 单个事务中的多线程

转载 作者:行者123 更新时间:2023-11-30 12:10:10 25 4
gpt4 key购买 nike

根据 this MSDN article ,您应该能够对一个进程进行多线程处理,每个线程都在一个根事务中登记。

我根据那篇文章创建了一个示例,其中我希望事务被回滚(bool[] 结果 应该在 foreach< 中全部为 false/循环)。不幸的是,情况并非如此,而且结果是不可预测的(运行该示例足够多次,您将在数组中看到 bool 值的任意组合)。

此外,我已经尝试了 DependentCloneOption.BlockCommitUntilCompleteDependentCloneOption.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();
}
}
}

最佳答案

你的 results[] 成员已经设置为 true 不会神奇地把自己设置回 false(很遗憾)。这就是事务管理器所做的。查看 EnlistXXX 方法以了解所涉及的内容。

基本上,您需要在回滚时进行补偿。例如,您可以订阅根事务的 TransactionCompleted 事件并检查事务是否已回滚。如果是,您需要为已完成的子 worker 恢复之前的值。

您还可以处理您正在抑制的抛出的 TransactionAbortedException,或在工作人员级别处理它(请参阅本页上的捕获它的示例:http://msdn.microsoft.com/en-us/library/ms973865.aspx)

通常,对于内存中的“事务”,您最好使用任务库让工作人员批量处理结果,然后在父任务的延续中“提交”它们。这比搞乱事务更容易,只有在内存和其他一些事务管理器(如 SQL Server 或其他进程)之间进行协调时才需要这样做。

关于c# - 单个事务中的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19261281/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com