C# 正在等待事件引发线程取消

C# 正在等待事件引发线程取消,c#,multithreading,events,cancellation,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

我有一个工作线程,它通过引发事件来报告进度

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
}
private volatile bool可以运行;
公开募捐
{
对于(int i=0;i
Cancel
方法中,我想等待线程完成。否则,有人可能会调用
Cancel
,然后在线程仍在“执行任务”时立即调用
Dispose
。如果我使用了
Join
,可能会出现死锁-UI等待线程取消,线程等待UI处理
ProgressMade
事件


有没有办法很好地解决这个问题,或者从一开始就是糟糕的设计?我当前的解决方案依赖于UI在处理工作者之前等待
WorkFinished
事件。

在注释中,您暗示您可能可以使用wait(即使在.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");
}
我们需要让我的员工合作:

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;
}
}
类MyWorker{
取消令牌ct=;
TaskCompletionSource shutdownCompletedTcs=新建…();
公开募捐
{
对于(int i=0;i
注意,所有等待操作都使用wait。它们在不中断控制流的情况下释放UI线程


还请注意,
MyWorker
是可协同取消的。它对UI一无所知。

您使用的是什么C版本?与等待这不是太难做到。为什么不加入取消方法?我想我没有明白你的意思。如果调用
Cancel
,则它将退出循环,但仍会调用
OnWorkFinished
。你不想处理什么?usr:我用的是C#4.0。我玩了一点
async/await
,但我对它不是很有信心。您的意思是等待
WorkFinished
事件,然后调用
Dispose
?Vadim:当工作线程引发
ProgressMade
事件并等待处理时,它会导致死锁。尤瓦尔:我想避免工人在离开for循环之前被处置的情况。它从文件中读取,然后
Dispose
关闭文件。+1:是的,我每次都会投票支持基于取消令牌的方法。