この MSDN 記事によると、各スレッドが単一のルート トランザクションに参加するプロセスをマルチスレッド化できるはずです。
その記事に基づいて、トランザクションがロールバックされることを期待するサンプルを作成しました (bool[] results
すべてfalse
がforeach
ループ内にある必要があります)。残念ながら、これは当てはまらず、結果は予測不可能です (例を十分に実行すると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();
}
}
}