3

我正在使用Multithreading來解決我的問題。我一直在使用Parallel.Foreach在後臺工作人員DoWork事件中執行長時間運行的作業。但是,當我不得不取消工作時會出現問題。它不會立即取消線程。立即取消所有正在運行的C#Parallel.Foreach線程

BackgroundWorker的DoWork的事件:

private void File_DoWork(object sender, DoWorkEventArgs e) 
{ 
    var cts = new CancellationTokenSource(); 
    btnCancel.Click += (cancelSender, cancelEvent) => 
       { 
        bgwFile.CancelAsync(); 

        if (bgwFile.CancellationPending) 
        { 
         cts.Cancel(); 
         e.Cancel = true; 
        } 
       }; 
    object sync = new object(); 
    List<Response> responses = null; 

    var parallelOperation = new ParallelOptions 
    { 
      MaxDegreeOfParallelism = 3, 
      CancellationToken = cts.Token 
    }; 

    Parallel.ForEach(listRequest, parallelOperation, request => 
    { 
     lock (sync) 
     { 
      responses = GetQueryResponse(request); // Long running process  
      parallelOperation.CancellationToken.ThrowIfCancellationRequested(); 
     } 
    }); 
    e.Result = responses ; 
} 

在這裏,問題是,當我不得不取消長時間運行的任務。假設有三個並行循環請求,如果有MaxDegreeOfParallelism = 3,那麼它就是GetQueryResponse(request)這個長工作的方法,如果我用CancellationTokenSource取消線程,那麼它不會立即取消這個進程。它只在執行3請求線程後才取消。

我想立即取消它。是否有立即取消Parallel.Foreach生成的所有正在運行的線程並轉到RunWorkerCompleted背景工作者事件的方法?

+1

至少你應該確保你的代碼片段在發佈之前編譯,由於'response'被聲明的範圍以外訪問,這可能不是這種情況。 –

+0

感謝kirill..Indeed,上面的代碼段是我的實際代碼的示例代碼...感謝您指出...... :) –

+1

呃,隨着你使用的鎖,你沒有任何並行的東西。據我所知... –

回答

3

您可以使用CancellationToken.Register Method (Action)註冊將在此CancellationToken取消時將被調用的代理。

一旦要求取消,它就會被解僱。當然,你必須寫出將導致當前GetQueryResponse執行立即停止的邏輯。

+0

+ 1 ..我會試着讓你知道結果.. –

+0

順便說一句,GetQueryResponse是長時間運行的IO操作(例如作爲搜索網絡中的文件)。有沒有辦法在運行時強行取消操作? –

+0

這取決於操作本身。沒有任何東西可以讓你明確地殺掉TPL任務,就像你使用Thread類的實例一樣。檢查這個答案:[我如何中止/取消TPL任務?](http://stackoverflow.com/questions/4783865/how-do-i-abort-cancel-tpl-tasks)。 – MarcinJuraszek

0

檢查TPL取消令牌。 here將CancellationToken傳遞給Parallel.Foreach()可以使其工作。當您要停止所有任務只需使用:

cts.Cancel()

內,您的任務的方法的地方

cts.Token.ThrowIfCancellationRequested(); 當你想檢查任務是否需要停止,因爲另一個任務取消了這個過程。

+0

我正在使用CancellationTokens,但它不能幫我立即取消所有線程.. –

-2

可以將線程的IsBackground屬性設置爲true。這會在您的應用完成時終止所有線程。

您可以使用一個計時器(或一個線程)來喚醒和檢查數據。這應該更加資源友好。