[英]How to queue/wait for TPL tasks to complete
我需要有关TPL和任务的帮助
这是我的情况:
我有一些产生任务的事件处理程序。 如果一个事件在其上一个任务完成之前被调用,我想在继续之前等待(阻止)它。
我有一个同步方法,该方法在被调用时必须等到任何事件处理程序产生的所有任务完成后再继续。
public void DoSomething()
{
// Expects any running tasks from OnEvent1(), OnEvent2(), OnEvent3()
// to be completed before proceeding.
}
public void OnEvent1()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
public void OnEvent2()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
public void OnEvent3()
{
Task.Factory
.StartNew(()=>{ /*Long running task*/ })
.ContinueWith(task=>{ /* Updates UI */ });
}
实际情况是:
OnSyncSettings() =>生成任务。 此后的所有后续调用都需要排队。
OnAutoBackup() =>同步方法。 保存之前,请等待其他任务(例如,“获取数据/同步”设置)完成。
我的问题很简单:我该怎么做?
这种方法正确吗?
每个事件处理程序都会记住其最后一个。 调用时,它将等待列表中的所有任务完成后再继续。
对于同步方法,它需要等待所有任务(从每个事件处理程序)执行
Task _lastEvent1Task;
public void OnEvent1()
{
// Wait for all tasks to complete before proceeding
if (_lastEvent1Task!=null)
_lastEvent1Task.Clear();
// Spawns new task
_lastEvent1Task = Task.Factory.StartNew(()=>{ });
}
public void OnEvent3()
{
// Wait for any running tasks to complete before proceeding
if (_lastEvent1Task != null) _lastEvent1Task.Wait();
if (_lastEvent2Task != null) _lastEvent2Task.Wait();
...
// Proceed
}
谢谢!
[编辑]
当DoSomething()正在等待并且引发Event1时? 如果DoSomething()正在运行并且引发了事件该怎么办?
OnEvents()
DoSomething() (调用时)
您描述的方法存在并发问题。 例如,在对_lastEvent1Task
进行null检查_lastEvent1Task
,其他线程可能_lastEvent1Task
设置为null,从而导致NullReferenceException
。
我假设每个任务都应该同步运行,但有些不应阻塞。 实现此目标的最佳方法是使用仅利用单个线程的TaskScheduler
,您可以在此处找到示例。
var scheduler = new SingleThreadedTaskScheduler();
var taskFactory = new TaskFactory(scheduler);
对于非阻塞方法,您将得到以下内容:
public void NonBlockingMethod()
{
taskFactory
.StartNew(() => { /* Long-running work. */ })
.ContinueWith(t => { /* Update UI. */ });
}
对于阻塞方法,您将获得:
public void BlockingMethod()
{
taskFactory
.StartNew(() => { /* Do work. */ })
.Wait();
}
在计划任务时,任务计划程序将仅使用一个线程来计划任务,从而确保所有任务都同步运行。
我认为您需要使用ParExtSamples中的任务计划程序。 通常,您需要为您的OnEvents的OrderedTaskScheduler(),然后等待所有预定的任务在DoSomething的完成()方法,或者干脆在同一OrderedTaskScheduler安排您DoSomething的()方法,它只会一次任务执行,预定在此之前,已经完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.