我有一个返回IEnumerable的类。然后我按顺序执行这些任务。假设该类是TaskProvider。
public class TaskProvider {
public IEnumerable<Task> SomeThingsToDo() { return work; }
}
我正在执行以下操作:
public void ExecuteTasks(IEnumerable<Task> tasks)
{
var enumerator = tasks.GetEnumerator();
ExecuteNextTask(enumerator);
}
static void ExecuteNextTask(IEnumerator<Task> enumerator)
{
bool moveNextSucceeded = enumerator.MoveNext();
if (!moveNextSucceeded) return;
enumerator
.Current
.ContinueWith(x => ExecuteNextTask(enumerator));
}
现在我的情况是,我可能有多个TaskProvider实例,每个实例都会生成一个任务列表。我希望每个任务列表按顺序执行,这意味着一个提供程序的所有任务在下一个提取程序开始之前完成。
然后,最重要的是,我需要知道所有任务何时完成。
TPL实现这个目标的方式是什么?
(FWIW,我正在使用Silverlight的Async CTP。)
答案 0 :(得分:1)
这是我采取的方法,到目前为止我所有的测试都已经过去了。
首先,我创建了一个联合各种提供者的所有任务的联合:
var tasks = from provider in providers
from task in provider.SomeThingsToDo()
select task;
我认为我原来问题的一部分是我做了一个ToList(或多或少),因此开始过早地执行任务。
接下来,我添加了对ExecuteTasks和ExecuteNextTask的回调。不可否认,并不像我希望的那样干净。以下是修订后的实施:
public void ExecuteTasks(IEnumerable<Task> tasks, Action callback)
{
var enumerator = tasks.GetEnumerator();
ExecuteNextTask(enumerator, callback);
}
static void ExecuteNextTask(IEnumerator<Task> enumerator, Action callback)
{
bool moveNextSucceeded = enumerator.MoveNext();
if (!moveNextSucceeded)
{
if (callback != null) callback();
return;
}
enumerator
.Current
.ContinueWith(x => ExecuteNextTask(enumerator, callback));
}
我不需要用于存储任务列表的线程安全结构,因为列表只生成一次。
答案 1 :(得分:0)
在最坏的情况下,你可以拥有一个Ienumerables的静态并发,你可以通过ExecuteNextTask方法来实现它......
类似的东西:
public static class ExecuteController {
private static ConcurrentQueue<IEnumerable<Task>> TaskLists = new ConcurrentQueue<IEnumerable<Task>>();
public void ExecuteTaskList(IEnumerable<Task> tasks) {
TaskLists.Enqueue(tasks);
TryStartExec();
}
public void TryStartExec() {
check if there is a new task list and if so exec it with your code.
possibly need to lock around the dequeue but i think there is an atomic dequeue method on concurrent queue..
}
}