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 的函数委托。

将这些委托传递给递归函数,并确保它将这些委托传递给每个递归调用。

当您想取消后台工作人员时,在递归函数中调用第一个委托。

最后,在递归函数中使用第二个委托检查挂起的取消。

这样您就不必传递后台工作人员。

于 2012-08-22T15:10:05.377 回答
1

您是否考虑过编写展开的递归 while 循环?“展开的递归循环”的优点是:

  • Stack<> 对象可以用完所有可用内存,但不会导致 stackoverflow
  • 无论工作队列有多深,都可以通过一次测试取消函数调用并返回
  • 如果愿意,您可以报告进度(例如进度百分比 = num_items_processed / 堆栈大小 + num_items_processed)
  • 您可以随时暂停执行并稍后恢复

这是展开递归的一种潜在实现:

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 回答