0

System.ComponentModel.BackgroundWorkerの使用方法についてはかなりよく理解しています。基本的には、単一の「DoWork」関数と、通常は機能するe.Cancelループと、ループを中断して停止するかどうかを判断するためにチェックする各反復があります。BackgroundWorkerの「DoWork」を終了します (これはすべて、WorkerSupportsCancellationプロパティが正しく設定されていることを前提としていますtrue)。

よくわからないのは、タスクを実行する再帰関数があるかどうかです (正確な関数は関係ありません。再帰関数は古典的な計算階乗としましょう) (ループではなく) どうすればこれを内部から呼び出すことができますか? 「DoWork」関数、そしてe.Cancelこの場合、再帰を回避するためにどのようにアップを伝播するのですか?

4

4 に答える 4

3

このようなことを意味しますか?キャンセルが開始されるとすぐに、再帰ループが一番上まで展開され、停止します。

void RecursiveLoop(BackGroundWorker worker)
{
  // ON entry check if we need to stop
  if (worker.CancellationPending) return;
  //
  // Normal code and the recursion
  if (morework) RecursiveLoop(worker);
}
于 2012-08-22T15:14:40.227 に答える
2

バックグラウンドワーカーをキャンセルする関数へのデリゲートを作成します。

バックグラウンドワーカーのキャンセルが保留中の場合にfalseを返す関数へのデリゲートを作成します。

これらのデリゲートを再帰関数に渡し、これらのデリゲートが各再帰呼び出しに渡されることを確認してください。

バックグラウンドワーカーをキャンセルする場合は、再帰関数で最初のデリゲートを呼び出します。

最後に、再帰関数で、2番目のデリゲートを使用して保留中のキャンセルを確認します。

このようにして、バックグラウンドワーカーを回す必要はありません。

于 2012-08-22T15:10:05.377 に答える
1

アンロールされた再帰的 while ループを書くことを考えたことはありますか? 「展開された再帰的ループ」の利点は次のとおりです。

  • Stack<> オブジェクトは利用可能なすべてのメモリを使い果たす可能性がありますが、stackoverflow は発生しません。
  • 関数呼び出しは、ワーク キューの深さに関係なく、1 回のテストとリターンでキャンセルできます。
  • 必要に応じて、進捗状況を報告できます (例: 進捗率 = num_items_processed / スタック サイズ + num_items_processed)
  • いつでも実行を一時停止し、後で再開できます

アンロールされた再帰の潜在的な実装の 1 つを次に示します。

void RecursiveLoop(WorkItem item)
{
    // Create a stack and push our item onto it
    Stack<WorkItem> recursion = new Stack<WorkItem>();
    recursion.Push(item);

    // Loop through all items in the stack
    while ((!cancel_flag_set) && (recursion.Count > 0)) {
        WorkItem current = recursion.Pop();

        // ... Do Work Here ...

        // Now, queue up all the child items
        foreach (WorkItem child in current.ChildItems) {
            recursion.Push(child);
        }
    }
}
于 2012-08-22T16:00:02.170 に答える
0

関数の先頭で確認e.Cancelし、真であればクラススコープにメンバ変数を設定する。その変数を使用して、続行するかどうかを決定します。

于 2012-08-22T15:15:54.460 に答える