C# 取消任务并等待它完成
我有一个耗时的任务,我需要在一个单独的线程中运行,以避免锁定GUI线程。随着此任务的进行,它将更新特定的GUI控件 问题是,在任务结束之前,用户可能会移动到GUI的另一部分,在这种情况下,我必须:C# 取消任务并等待它完成,c#,task-parallel-library,C#,Task Parallel Library,我有一个耗时的任务,我需要在一个单独的线程中运行,以避免锁定GUI线程。随着此任务的进行,它将更新特定的GUI控件 问题是,在任务结束之前,用户可能会移动到GUI的另一部分,在这种情况下,我必须: 取消正在进行的任务(如果它处于活动状态) 等待完成取消:这是至关重要的,因为耗时任务的目标是更新特定控件。如果一次有多个线程尝试这样做,事情可能会变得一团糟 从头开始启动任务 对于一个具体的例子,假设表单有两个部分:一个是导航目录树的部分,另一个是显示缩略图的部分。当用户导航到另一个目录时,需要刷新缩
后台工作人员
和一个自动恢复事件
来等待取消,但我一定是弄糟了什么,因为取消时我陷入了僵局。然后我读了关于TPL的书,它应该取代BGW和更原始的机制
使用第三方物流可以轻松做到这一点吗?需要注意的几点:
- 您可以从
CancellationTokenSource
- 任务取消是一种合作的操作:如果您的任务没有定期检查
属性,无论您尝试取消任务多少次,它都会愉快地消失CancellationToken.IsCancellationRequested
void Main()
{
var tokenSource = new CancellationTokenSource();
var myTask = Task.Factory
.StartNew(() => DoWork(tokenSource.Token), tokenSource.Token);
Thread.Sleep(1000);
// ok, let's cancel it (well, let's "request it be cancelled")
tokenSource.Cancel();
// wait for the task to "finish"
myTask.Wait();
}
public void DoWork(CancellationToken token)
{
while(!token.IsCancellationRequested)
{
// Do useful stuff here
Console.WriteLine("Working!");
Thread.Sleep(100);
}
}
只创建一次令牌源并每次将其令牌传递给
StartNew
可以吗?将其想象为一个孩子在字符串上的两个罐子(一到N个罐子:你有一个末端,所有开始的任务都有一个罐子。你喊“取消”一方面,所有共享令牌的人都会听到它。@dario_ramos我相信你评论中的问题在评论中得到了回答,但为了完整起见,答案是否定的-CancellationTokenSource
不能再次重置和取消;如果你请求取消一个令牌,那么如果你想,你必须用一个新的替换它再次取消。@bohdan\u trotsenko该示例使用了一个称为synchronously的非异步方法。在同步方法中,正确的等待方式是Thread.Sleep
。当心.Task.wait将抛出一个AggregateException,指示任务已取消(您已经知道,因为您已取消了它)。