我需要一些关于TPL和Tasks的帮助。
这是我的场景:
我有几个事件处理程序,它们会生成任务。如果在前一个任务完成之前调用了事件,则我希望等待(阻塞)它,然后再继续执行。
我有一个同步方法,当调用时,必须等待任何事件处理程序生成的任务完成后才能继续执行。
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 */ });
}
一个实际的场景如下:
- OnFetchData() => 生成任务。此后对该任务的所有调用都需要排队。
OnSyncSettings() => 生成任务。此后对该任务的所有调用都需要排队。
OnAutoBackup() => 同步方法。在保存之前等待其他任务(例如,获取数据 / 同步设置)完成。
- OnFullBackup() => 同步方法。手动运行 FetchData() 和 SyncSettings(),等待完成,然后继续执行。
我的问题很简单:我该如何做呢?
这种方法是否正确?
每个事件处理程序都记得它的上一个。当调用时,它将等待其列表中的所有任务完成后再继续执行。
对于同步方法,它需要等待所有任务(来自每个事件处理程序)完成才能继续执行。
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()
- 如果是第一个任务:生成任务并异步执行
- 如果前一个任务仍在运行,则排队/阻塞。关键部分。
- 假设:
- 这些事件通常不会被多次触发。
- UI预计会防止用户在仍在运行时引发相同的事件。
DoSomething()(调用时)
- 假设:事件通知已禁用。
- 假设:不会有新的事件排队。
- 期望:等待所有剩余的排队任务完成后再继续。
- 期望:是同步调用,并且在执行完成之前不会返回给调用者。
DoSomething()
正在等待并且Event1
被触发时,应该发生什么?事件代码是否应该等待DoSomething()
完成?还是DoSomething()
也应该等待新事件?如果DoSomething()
正在运行并且事件被触发会怎样? - svick