C # BackgroundWorker Отмена сокращения контрольной точки - PullRequest
2 голосов
/ 04 августа 2011

Есть ли способ сократить мою 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 ]

5 голосов
/ 04 августа 2011

Нет способа вызвать метод A для вызова methodB и позволить methodB вернуть метод A (поскольку у нас нет хвостовой рекурсии)Это будет работать в некоторых ситуациях, когда вы можете поставить контрольные точки try / catch между *. 1003 *

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 голос
/ 04 августа 2011

Вы можете использовать mono.Cecil для перезаписи IL. Вы можете украсить метод атрибутом «Cancellable», а затем переписать любые методы с этим атрибутом. Вам потребуется создать CFG из потока инструкций, написать некоторый код для вычисления глубины стека, определить места, где глубина стека равна нулю, добавить узлы для проверки отмены, а затем повторно выполнить сериализацию CFG в тело метода. Это, вероятно, займет около недели, плюс время, чтобы проверить все. Вы также должны добавить шаг пост-сборки.

Как правило, если у вас нет большого количества отменяемых методов, это, вероятно, не стоит.

...