等待事件提升线程取消

时间:2014-06-16 11:25:15

标签: c# multithreading events cancellation

我有一个工作线程,通过举办活动来报告进展情况。

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,而线程仍然是&#34;做东西&#34;。如果我使用Join,则可能存在死锁 - UI等待线程取消,线程等待UI处理ProgressMade事件。

有没有办法很好地解决这个问题,还是从一开始就设计不好?我当前的解决方案依赖于在处置worker之前等待WorkFinished事件的UI。

1 个答案:

答案 0 :(得分: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;
}
}

(快速打耳光。)注意,所有等待操作都使用await。他们在不中断控制流的情况下释放UI线程。

另请注意,MyWorker可以合作取消。它对UI没有任何了解。