1

BackgroundWorker の使用に問題があります。何が起こるかというと、BackgroundWorker プロセスが正常に機能し、開始するまでに 40 ~ 50 秒かかることがあります。

問題は 2 台のマシンで発生しました。BackgroundWorker 操作は 1 日を通して正常に機能していましたが、午後になるとこの問題が発生し始め、プロセスに 1 秒ではなく 40 秒かかるようになりましたが、これはまれにしか発生しませんでした。そのうちの 5 つを問題なく実行でき、6 つ目は 40 秒かかります。その後、さらに 5 罰金を行うことができます。1 秒以上かかるようになった場合は、workingDialog でキャンセルを押してすぐにやり直すと、機能します。さらに調べてみると、ワーカーはすぐに DoWork メソッドを開始していないようです。

スレッドか何かが不足している可能性がありますか?それとも、BackgroundWorker の破棄方法に問題があるのでしょうか? コードは以下のとおりです。

using (workingDialog = new Dialogs.WaitDialog()) {
    StartThreadedWork(MyDoWorkMethod, customerID);

    // if user presses cancel button
    if (workingDialog.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) {
        m_Worker.RunWorkerCompleted -= ThreadFinished;
    }
}
m_Worker.Dispose();
m_Worker = null;

「StartThreadedWork」メソッドは以下のとおりです。

private void StartThreadedWork(DoWorkEventHandler method, int customerID) {
    m_Worker = new BackgroundWorker();
    m_Worker.DoWork += method;
    m_Worker.RunWorkerCompleted += ThreadFinished;
    object[] parameters = new object [] {customerID };
    m_Worker.RunWorkerAsync(parameters);
}

最後に、DoWork イベント ハンドラに割り当てられるメソッドは次のとおりです。

private void ThreadSyncing(object sender, DoWorkEventArgs e) {
    object[] parameters = e.Argument as object[];
    int customerID = (int)parameters[0];
    Customer resultCustomer = new Customer(FormsManager.Instance.BillingWebService.Customer_GetByCustomerID(customerID, CustomerSyncOption.Default));
    e.Result = resultCustomer;
}

RunWorkerCompleted イベントが発生すると、ダイアログの結果が OK に設定され、ダイアログが閉じます。

これに関する任意のポインタは非常に高く評価されます!

ありがとう、

4

2 に答える 2

2

遅れたのは実際に BGW の開始であったことをどうやって知ることができますか? フィードバックはありません。完了したことだけがわかります。Web サービスを使用しているように見えますが、サーバーが 40 秒間応答しない、または要求を完了していないことは異常ではありません。デフォルトの tcp/ip 接続タイムアウトは 45 秒です。

ThreadPool スケジューラが役割を果たすことができ、実行中の TP スレッドの数をマシンの CPU コア数に制限しようとします。ただし、40 秒の遅延が発生するのは、まれなケースです。スケジューラーは、既存の TP スレッドが完了しない場合に、1 秒に 2 回、別の TP スレッドを開始できるようにします。したがって、そのような遅延が発生するには、80 のアクティブな TP スレッドが必要になります。

使用するダイアログについて注目すべきことの 1 つは、ワーカー スレッドを停止するために実際には何もしないことです。それはただそれを放棄します。そのため、サーバーが応答せず、ユーザーが焦ると、ビルドアップする可能性があります. 足を4回叩いた後、キャンセルボタンを連打。それ着実に増加する遅延を引き起こします。CancelAsync() メソッドを使用し、CancellationPending プロパティを使用してキャンセル ロジックを実装することになっています。しかし、そうです、通常、これを Web サービスで行うのは簡単ではありません。

より良いフィードバックを提供することで、その問題を解決します。ユーザーがキャンセルした場合、RunWorkerCompleted イベントのサブスクライブを解除しないでください。最後のリクエストがキャンセルされたことを示すフラグを設定するだけです。ワーカーが完了するまで Web サービスが利用できないことを UI に表示します。ユーザーが Web サービス要求を再度開始できないようにすることも含まれます。

于 2012-09-09T21:26:00.563 に答える
1

BackgroundWorker は、.Net スレッド プールを使用して DoWork メソッドを実行します。

スレッド プールに負荷をかけすぎると、一部の作業項目は、それらを処理するスレッドが利用可能になるまで遅延します。

于 2012-09-09T16:57:47.740 に答える