2013-06-28 97 views
6

我有一個任務,我想要取消。停止任務而不會丟棄取消取消

這樣做的通常方法是用CancellationToken

this.task = new SpecialTask(() => 
{ 
    for (int i = 0; i < ushort.MaxValue; i++) 
    { 
     CancelToken.ThrowIfCancellationRequested(); 
     Console.WriteLine(i); 
    } 
}, this.CancelToken); 

但是,在現實世界中,事情從未如此簡單。 我們的異步代碼不能循環,它看起來是這樣的:

this.task = new SpecialTask(() => 
{ 
    CancelToken.ThrowIfCancellationRequested(); 
    Operation1(); 

    CancelToken.ThrowIfCancellationRequested(); 
    Operation267(CancelToken); 

    CancelToken.ThrowIfCancellationRequested(); 
    object232.Operation345(); 

    CancelToken.ThrowIfCancellationRequested(); 
    object99.Operation44(CancelToken); 

    CancelToken.ThrowIfCancellationRequested(); 
    Operation5(CancelToken); 

    ... 

    CancelToken.ThrowIfCancellationRequested(); 
    Operation...n(CancelToken); 

}, this.CancelToken); 

我用的對象和方法名隨機數字表明,沒有循環可以創建任何。

什麼是最費心是,我必須保持一遍又一遍寫相同CancelToken.ThrowIfCancellationRequested()

而且,彷彿這還不夠,我要拖CancellationToken遍了我的代碼只是爲了能夠停止長時間運行的操作 - 根據微軟 - 在正確的時間。

說了這麼多,有沒有辦法,我可以免除這些重複調用,毒我的代碼嗎?

我們也知道,使用

try 
{ 
    task.Wait(cancelToken); 
} 
catch(OperationCancelledException) 
{ 
} 

OperationCancelledException被拋出和捕獲的Wait方法時。但是,如果不時檢查CancelToken.ThrowIfCancellationRequested(),則任務執行的長操作不會停止。

是否有任何可能的方式,使內停止運行時異常被捕獲的等待?

+0

的[異步中止C#TPL任務]可能重複(http://stackoverflow.com/questions/17321692/asynchronously-abort-c-sharp-tpl-tasks) – dtb

+1

請參閱[如何取消不可取消的異步操作?](http://blogs.msdn.com/b/pfxteam/archive/2012/10/05/如何做 - 我 - 取消 - 不可取消 - 異步操作.aspx)總之,你不。您需要這樣做,否則您根本無法取消任務。也就是說,你可以對這段代碼做一些重構,以避免一些重複。 – Servy

+0

雖然我確實瞭解確保長時間運行的操作在合適的時間停止的必要性,但我希望框架在較低的層次上可以有一些內置的良好取消機制。儘管如此,我會盡快查看您提供的鏈接。謝謝! – Paul

回答

2

你可以重構你的代碼進入一個循環,以避免各線之間的重複取消:

var actions = new List<Action>() 
{ 
    ()=>Operation1(), 
    ()=>Operation267(CancelToken), 
    ()=>object232.Operation345(), 
    //... 
}; 

foreach (var action in actions) 
{ 
    action(); 
    CancelToken.ThrowIfCancellationRequested(); 
} 
+0

這將要求我想象我的代碼分離方法的更細粒度。我幾乎被迫分成更小的方法,而不是採用3種很好的可靠方法,以便儘快取消註銷。 Elliminating從一處代碼nuissance並添加另外一個別的地方也做不了 – Paul

+1

@保羅你仍然可以通過取消標記進入方法和做那些同樣的事情,仍允許代碼重構爲方法。 – Servy