2010-08-05 38 views
3

什麼是在一個C#程序中創建一個「取消」事件的最有效方法,該程序正在一個單獨的線程上處理一個循環中的大量數據集?有效取消數字處理線程的事件實現?

現在,我只是簡單地使用從我的UI線程觸發的cancel事件,該事件隨後在數字運算線程上調用「onCancel」函數。該取消函數將變量設置爲「真」,緊縮回路定期檢查該變量,例如,

Class Cruncher { 
    private bool cancel = false; 

    public cruncher() 
    { 
     crunch(); 
    } 

    private void crunch() 
    { 
     while(conditions AND !cancel) { crunch; } 

     dispose_resources; 
    } 

    private void onCancel() 
    { 
     cancel = true; 
    } 
} 

雖然我沒有檢查經常取消變量作爲我的榜樣以上(而不是實際執行不取消),我還是想優化這個緊縮方法儘可能。任何更有效地完成這個例子的例子都會很好看。

+1

在非常緊密的循環中,我通過僅檢查每100或1000次迭代而不是每次迭代來進行優化。但你必須檢查。 – 2010-08-05 22:04:31

回答

3

取消事件/標誌應該是一個volatile ......我問了一個非常類似的問題給你:Is it safe to use a boolean flag to stop a thread from running in C#

我也建議您何時取消線程你等待他們都用取消類似於C# version of CountDownLatch。當你想保證線程被取消時,這很有用。

+0

你的問題是我試圖在我的搜索中找到的問題! – rnd 2010-08-06 00:00:05

+0

@rnd,很高興我能幫忙! – Kiril 2010-08-06 00:10:01

1

它最終總是會導致類似這樣的事情 - 儘管重要的是您要使cancel變量易變,否則工作線程可能看不到取消線程的更改。

你一定要檢查東西週期性,除非你想要去中斷線程(我推薦)的更激烈的路線。檢查單個布爾標誌不太可能是昂貴的......如果你可以在循環的每次迭代中做一個合理的工作塊(足以遏制檢查的成本),那很好。

如果你需要使用的等待形式進行任何等待,但是,(在工作線程),然後您可以改善的事項(如Monitor.Wait),它允許取消線程喚醒任何提前等待線索。這不會使正常操作更有效率,但它會允許線程在取消時更快地終止。

+0

C#in Depth目前正在從亞馬遜前往我的路上。期待它! – rnd 2010-08-06 00:08:58

0

我會這樣做。我還會將Thread.Sleep添加到循環中,以便對主線程進行控制。

http://msdn.microsoft.com/en-us/library/7a2f3ay4%28VS.80%29.aspx

+0

當有適當的信令實現(即Monitor或CountDownLatch)時,我不認爲Thread.Sleep是必需的。 – Kiril 2010-08-05 18:57:40

+0

同意,我正在談論一個循環內的簡單變量檢查。 – akonsu 2010-08-05 19:08:30

1

特別是因爲它的UI觸發的,我會建議只是撬動BackgroundWorker中已有的框架內,特別是因爲它會很好地有進展,並在UI線程上做一些事情的發生你(這麼你不必自己調用它)。

然後您可以使用CancelAsync()調用。無可否認,它與你已經在做的沒有什麼不同,只是在框架中完成(包括線程同步邏輯)

正如Jon所說,你仍然想要做合作取消(檢查CancellationPending在你的DoWork中使用BackgroundWorker),因爲'中斷/中止線程'選項是你想盡可能避免的。

如果在.NET 4中,您可以使用TPL和new Cancellation support,但它又一次着重於協作取消。

+0

感謝您提供關於後臺工作人員的提示,James。我會考慮轉移到這個而不是我自己的實現,因爲我的線程系統目前是臨時測試容器。 – rnd 2010-08-06 00:01:05

1

我推薦使用.NET 4.0中引入的unified cancellation model(如果.NET 4.0是一個選項)。

這是非常有效的,並允許與Task對象和並行LINQ集成取消。