2

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());

しかし、結果は同じです。

4

2 に答える 2

2

リポジトリは、更新ごとに新しいデータコンテキストを作成する必要があります。それぞれが単一の作業単位にのみ使用されることになっています。これを試して:

public static void ProcessingStarted(int messageId)
{
    using (DataContext dc = new DataContext())
    {
        var update = dc.QueuedMessages.SingleOrDefault(m => m.Id == messageId);
        if (update != null)
        {
            update.ProcessingStarted = true;
            dc.SubmitChanges();
        }
    }
}
于 2012-07-18T19:21:20.127 に答える
1

SubmitChanges が必要ですか? プロデューサーが毎回同じ DataContext インスタンスを使用している場合、既にメモリにあるものを返す必要があります。

各チェックで新しい DataContext を使用する場合は、新しい DataContext で各 SubmitChanges を実行します。

于 2012-07-18T19:51:38.323 に答える