SOで同様のスレッドを見つけましたが、正確な問題に対処しているようには見えません。
基本的に、.NET タスク並列ライブラリを使用して単純なプロデューサー/コンシューマー アプリを作成しました。プロデューサは、データベース テーブルのレコードを 30 秒間隔でチェックします。レコードが見つかると、それらを に追加しますBlockingQueue
。その間、私Task.Factory
はレコードに対していくつかのアクションを実行していました。
レコードに対してアクションを実行しようとしているときに、レコードのフィールドを更新して、既にキューに入っていることを示したいと考えています。これは、最後のバッチがまだ処理されている間にプロデューサが新しいレコードをチェックする場合、古いエントリをキューに戻さないようにするためです。
SubmitChanges()
私が直面しているこの問題は、複数のスレッドからデータ コンテキストを呼び出すことです。競合状態を実行していると思いますが、よくわかりません。
私が得るエラーはThe operation cannot be performed during a call to SubmitChanges.
プロデューサーコード:
BlockingCollection<QueuedMessage> workItems = new BlockingCollection<QueuedMessage>();
System.Threading.Timer workItemTimer = new System.Threading.Timer((s) =>
{
var items = repository.GetQueuedMessages();
foreach (var item in items)
{
workItems.Add(item);
}
}, null, 0, 30000);
消費者コード:
while (workItems.TryTake(out queuedMessage, Timeout.Infinite, new CancellationToken()))
{
Task.Factory.StartNew((t) =>
{
var messageToSend = (QueuedMessage)t;
repository.MarkQueuedMessageAsProcessing(messageToSend.Id);
...
Do some stuff with messageToSend
....
}, queuedMessage);
}
リポジトリ コード:
var entity = DataContext.QueuedMessages.SingleOrDefault(m => m.Id == messageId);
entity.ProcessingStarted = true;
DataContext.SubmitChanges();
キューに入れられたいくつかのメッセージでこれを実行すると、DataContext.SubmitChanges()
前述のメッセージで例外がスローされ始めます。The operation cannot be performed during a call to SubmitChanges.
私が言ったように、これは複数のスレッドから呼び出しているためだと思いますが、これを回避する方法がわかりません。
問題のある行を次のように変更してみました。
ThreadPool.QueueUserWorkItem(s => DataContext.SubmitChanges());
しかし、結果は同じです。