C#BackgroundWorker取消检查点缩短

时间:2011-08-03 22:57:57

标签: c# backgroundworker return checkpoint

有没有办法缩短我的 BackgroundWorker.CancellationPending 检查点?

例如,有没有办法像下面的示例代码一样封装return?:

//REAL CODE (CURRENTLY USE THIS)
if (this.TW.CancellationPending) 
    return; 

//PSEUDO REPLACEMENT CODE
this.CkPt(CurrentMethod); //PSEUDO USAGE 
    //^^^ PARAMETER IS A REFERENCE TO THE CURRENT METHOD, SIMILAR TO `this` FOR AN OBJECT  
//OR MAYBE AN EXTENSION METHOD WOULD LOOK CLEANER
CurrentMethod.CkPt(); //PSEUDO USAGE

private void CkPt(Method m) //PSEUDO METHOD
{
    /*
        POSSIBLY PERFORM OTHER CHECKPOINT TASKS HERE
    */
    if (this.TW.CancellationPending) 
        m.return/*FROM METHOD THAT CALLED ME*/;
}  

我正试图使这样的多检查点情况更具可读性:

//PSUEDO METHOD 
//DO NOT TAKE THIS AS REPEATING CODE
//IT IS ONLY MEANT TO SHOW MULTIPLE USES OF THE SAME CHECKPOINT
//MY REAL TASK METHOD(S) CONTAIN MANY MANY MANY AREAS THAT DON'T REPEAT AND REQUIRE CHECKPOINTS  
public void FakeBWTask()
{
    if (this.TW.CancellationPending) 
        return; 

    foreach (var F1 in Fake1)
    {
        if (this.TW.CancellationPending) 
            return; 

        foreach (var F2 in Fake2)
        {   
            if (this.TW.CancellationPending) 
                return; 
            foreach (var F3 in Fake3)
            {
                if (this.TW.CancellationPending) 
                    return; 
            }
        }
    }
}

感谢您的帮助!!

2 个答案:

答案 0 :(得分:5)

没有办法调用methodA来调用methodB并让methodB返回methodA(因为我们没有尾递归)

考虑使用像这样的迭代器。它可以在某些情况下工作,你可以将try / catch置于检查点之间。

public void FakeBWTask()
{
   if (this.TW.CancellationPending) 
      return; 
   foreach (object ignore in FakeBWTaskSteps())
   {
      // Other checkpoint logic here....
      if (this.TW.CancellationPending) 
          return; 
   }
}

private IEnumerable<object> FakeBWTaskSteps()
{
   Part1();
   yield return null; // Execute checkpoint logic.

   Part2();
   yield return null; // Execute checkpoint logic.

   Part3();
   yield return null; // Execute checkpoint logic.

   Part4();
   yield return null; // Execute checkpoint logic.

   // Do some other stuff.
   yield return null; // Execute checkpoint logic.

   // final stuff.  No looping here.
}

答案 1 :(得分:1)

您可以使用mono.Cecil进行IL重写。您可以使用“可取消”属性修饰方法,然后使用该属性重写任何方法。您需要从指令流构建CFG,编写一些代码来计算堆栈深度,识别堆栈深度为零的位置,注入节点以执行取消检查,然后将CFG重新序列化为方法体。它可能需要大约一个星期,加上测试一切的时间。您还必须添加一个帖子构建步骤。

一般来说,除非你有很多可取消的方法,否则它可能不值得。