开发者

C# BackgroundWorker Cancellation checkpoint shortening

开发者 https://www.devze.com 2023-03-24 21:39 出处:网络
Is there a way to shorten my BackgroundWorker.CancellationPending checkpoint? For example, is there a way to encapsulate return like the example code below?:

Is there a way to shorten my BackgroundWorker.CancellationPending checkpoint?

For example, is there a way to encapsulate return like the example code below?:

//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 ME开发者_高级运维THOD, 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*/;
}  

I'm trying to make multi-checkpoint situations like this more readable:

//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; 
            }
        }
    }
}

Thanks for any help!!


There is no way call for methodA to call methodB and let methodB return methodA (since we don't have tail recursion)

Consider using an iterator like this. It will work in some situations where you can put try/catch in-between checkpoints.

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.
}


You could use mono.Cecil to do IL rewriting. You could decorate a method with a "Cancellable" attribute, and then rewrite any methods with that attribute. You would need to build a CFG from the instruction stream, write some code to compute stack depths, identify places where the stack depth is zero, inject nodes to do the cancel check, and then reserialize the CFG into a method body. It would probably take about a week, plus time to test everything. You'd also have to add a post build step.

Generally, unless you have a lot of cancelable methods, its probably not worth while.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号