我有一个这样运行的任务数组:(数组中的任务数不固定为2,它可能会不时变化)。
Task[] templates = new Task[2] {
Task.Factory.StartNew( () => { x.foo(); }),
Task.Factory.StartNew( () => { y.bar(); })
};
然后我等待其中任何一个完成。
int taskID;
taskID = Task.WaitAny(templates);
任务完成后,我将检查对象内的各种参数(x或y),如果没有结果,我希望从模板数组中删除完成的任务。像这样
template[taskID].RemoveThisTaskFromArray() // This is pseudo code to describe what I want.
taskID = Task.WaitAny(templates);
我将循环执行此操作,直到任务数组template[]
为空,或者我决定中止该操作并退出循环为止。
int taskID;
do {
taskID = Task.WaitAny(templates);
if(template[taskID].valid == true) { // <-- example of test for success
// stop the remaining task in the template[] array.
break;
}
// remove the completed task so we can use WaitAany() again.
} while (template.Length > 0);
似乎Task[]
不支持数组成员,因此没有Task[].RemoveAt()
函数。
希望你明白我的意思。有什么办法解决这个问题?
答案 0 :(得分:1)
只需使用List<Task>
即可。但是,出于described in detail here的原因,请使用Task.Run
代替Task.Factory.StartNew
。
var templates = new List<Task> {
Task.Run( () => { x.foo(); }),
Task.Run( () => { y.bar(); })
};
int taskID;
do {
taskID = Task.WaitAny(templates.ToArray());
if(templates[taskID].valid == true) { // <-- example of test for success
// stop the remaining task in the template[] array.
break;
}
templates.RemoveAt(taskID);
} while (template.Count > 0);
这将调用.ToArray()
,这将创建一个新数组(preserving order),因此效率稍低,但是可以正常工作。这确实是提供Task.WaitAll
所需数组的最简单方法,同时保留了轻松删除项目的能力。
但是我不知道您打算如何使用template[taskID].valid
。您是否要使用templates
(带有's')数组? (这就是我的假设)但是Task
没有任何称为valid
的属性。您是说看看Status
属性吗?
但是,您可以考虑使用async
和await
并使用Task.WhenAny
来避免在等待时阻塞当前线程。 Task.WhenAll
也接受任何IEnumerable
,因此您无需致电.ToArray()
。
do {
var doneTask = await Task.WhenAny(templates);
// This will return any result, but also throw any exception that
// might have happened inside the task.
await doneTask;
templates.Remove(doneTask);
} while (templates.Count > 0);
从这里开始,有一些写得很好的关于异步编程的文章:Asynchronous programming with async and await
答案 1 :(得分:0)
可以使用linq这样从任务列表中删除完成的任务
templates.RemoveAll(x => x.IsCompleted);