2014-06-16 64 views
3

我有一個工作線程通過引發事件來報告進度。等待事件提升線程取消

private volatile bool canRun; 

public void Run() 
{ 
    for (int i = 0; i < count && canRun; i++) 
    { 
     // do stuff 

     OnProgressMade((float)i/(float)count); 
    } 

    OnWorkFinished(); 
} 

public void Cancel() 
{ 
    canRun = false; 

    // wait for the thread to finish 
} 

Cancel方法中,我想等待線程完成。否則,有人可能會呼叫Cancel,然後立即Dispose,而線程仍在「做東西」。如果我使用Join,則可能存在死鎖 - UI等待線程取消,線程將等待UI處理ProgressMade事件。

有沒有辦法很好地解決這個問題,還是從一開始就是糟糕的設計?我當前的解決方案依賴於在處理工作人員之前等待WorkFinished事件的UI。

+2

你使用的是什麼C#版本?等待這不是很難做到。 – usr

+0

爲什麼不加入取消方法? – Vadim

+0

我想我沒有趕上你的漂移。如果你調用'Cancel',那麼它將退出循環,但仍然調用'OnWorkFinished'。你不想處置什麼? –

回答

2

在評論中提示您可以使用await(即使在.NET 4.0上也可以)。它看起來是這樣的:

MyWorker w; 
CancellationTokenSource cts; 

void OnStart(eventargs bla bla) { 
cts = new ...(); 
w = new ...(cts.Token); 
} 

void OnCancel(eventargs bla bla) { 
cts.Cancel(); 
await w.WaitForShutdown(); 
MsgBox("cancelled"); 
} 

而我們需要做MyWorker合作:

class MyWorker { 
CancellationToken ct = <from ctor>; 
TaskCompletionSource<object> shutdownCompletedTcs = new ...(); 

public void Run() 
{ 
    for (int i = 0; i < count && !ct.IsCancellationRequested; i++) 
    { 
     // do stuff 

     OnProgressMade((float)i/(float)count); 
    } 

    //OnWorkFinished(); //old 
    shutdownCompletedTcs.SetResult(null); //new, set "event" 
} 

public Task WaitForShutdown() { 
return shutdownCompletedTcs.Task; 
} 
} 

(快速拼湊。)注意,所有的等待操作使用等待。他們在不中斷控制流的情況下釋放UI線程。

另請注意,MyWorker可合作取消。它不知道UI的任何內容。

+1

+1:是的,我每次都會爲基於取消令牌的方法投票。 – code4life

+0

這與我想要的完全一樣。謝謝。 –