6

コードでエラーがどのように発生しているかを把握しようとしています。例外は、コミットが既に進行中であることを示していますが、への呼び出しSaveChangesが非同期でない限り、それがどのように起こっているのかわかりません。

複数のオブジェクトを保持するSchedulerクラスがあります。TaskそれぞれTaskBackgroundWorker、別のスレッドで処理を行う があります。Task次に、次のコードを使用して、この BackgroundWorker 完了イベントのイベント ハンドラーをクラスに用意します。

private void TaskWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (!(e.Result is TaskResult))
        throw new ArgumentException("Result must be a TaskResult class.");

    TaskComplete((TaskResult)e.Result);
}

まだ私と一緒に?したがって、次のコードをTaskComplete使用してメインクラスで処理するイベントを発生させるタスククラスにこのイベントハンドラーがあります。Scheduler

private void TaskCompleted(object sender, TaskCompletedEvent e)
{
    Model.Task scheduledTask = entitySet.Tasks.First(x => x.TaskName == e.ClassName);
    TaskLog logMsg = new TaskLog()
    {
        //stuff here
    };

    scheduledTask.TaskLogs.Add(logMsg);
    entitySet.SaveChanges();
}

この時点で、私の理解では、バックグラウンド ワーカーで行われた作業が完了したため、メイン スレッドに戻っています。非常に頻繁に 5 つのタスクを実行していたとき、SaveChanges でコミットが既に進行中であるという例外が発生していました。このコンテキストをスレッド間で共有していないため、これがどのようになるかわかりません。これが起こっていることを確認できる唯一の方法は、SaveChanges が非同期 (ブロッキング呼び出しではない) である場合です。TaskCompleted 内のコードを using ステートメントでラップすると、新しいコンテキストで修正されることはわかっていますが、その理由を知りたいです。そして、なぜ現在の状態で機能しないのですか。

最後に、Telerik の OpenAccess ORM を使用しています。

4

2 に答える 2

0

おそらく、DbContext複数のスレッド間で a を共有しています。

マルチスレッド環境で DB を操作する場合は、オブジェクトの操作を開始する前に、オブジェクトを切り離す (つまり、プロキシや遅延読み込みを使用しない) 方がよいでしょう。DbContext次に、タスクごとに新しいオブジェクトを作成し、オブジェクトを添付して変更を保存します。

ただし、速度は低下します。コンテキストを共有したい場合はDbContext、タスクごとに増加し、各タスクが完了すると減少するカウンターを保持する必要があります。最後に、カウンターが再びゼロになったときにのみ変更を保存します。

于 2013-02-04T15:24:32.963 に答える
0

次のようにコミットを同期してみてください。

private static object _syncObject = new object();

private void TaskCompleted(object sender, TaskCompletedEvent e)
{
    Model.Task scheduledTask = entitySet.Tasks.First(x => x.TaskName == e.ClassName);
    TaskLog logMsg = new TaskLog()
    {
        //stuff here
    };

    scheduledTask.TaskLogs.Add(logMsg);
    lock(_syncObject){
        entitySet.SaveChanges();
    }
}
于 2013-02-02T19:51:33.113 に答える