我正在尝试创建一个取消方法,以确保任务已通过阻止调用者正常停止,直到它停止。
由于某种原因,我陷入了僵局,我认为这是因为cancel.Set()
发生在之前cancel.WaitOne()
,然后会等待另一个 cancel.Set()
,它不会到来。
我想知道如何解决这个僵局。
这是实际代码,剥离了业务逻辑:
ManualResetEvent cancel = new ManualResetEvent(true);
Queue<string> queue;
bool run;
public void Start()
{
run = true;
ThreadPool.QueueUserWorkItem(Work);
}
public void Cancel()
{
if (!run)
{
return;
}
cancel.Reset();
run = false;
Requests.Clear();
if (queue != null)
queue.Clear();
cancel.WaitOne();
}
private void Work(object state)
{
//fill queue depending on requests
while (queue.Any() && Requests.Any() && run)
{
//fill queue some more recursively
//remove requests as they are processed
}
//BUG: Deadlock
cancel.Set();
}
如您所见,这几乎是我之前发布的内容。(要么是那个,要么我是盲人)
更新
我最终使用了这样的任务:
Task activeItem;
bool run;
public void Start()
{
if(run)
return;
run = true;
activeItem = Task.Factory.StartNew(Work);
}
public void Cancel()
{
if (!run)
{
return;
}
run = false;
Requests.Clear();
if (queue != null)
queue.Clear();
activeItem.Wait(500);
}
private void Work()
{
//fill queue depending on requests
while (queue.Any() && Requests.Any() && run)
{
//fill queue some more recursively
//remove requests as they are processed
}
}
通过将超时添加到任务中,我发现了一个非常奇怪的行为:整个取消方法似乎阻塞了整个工作()线程/任务。只有在 Cancel() 完成后,Work()-Thread 才会继续。Cancel是通过UI Thread调用的,怎么会这样呢?