在this question之后(及其答案)我想使用TaskCompletionSource和Task.WhenAll
等待任何任务首先返回True。所以我写了这个:
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
Task<bool> t0 = Task.Factory.StartNew<bool>(() => Find(paramA, paramB);
Task<bool> t1 = Task.Factory.StartNew<bool>(() => Find(paramC, paramD);
Task<bool> t2 = Task.Factory.StartNew<bool>(() => Find(paramE, paramF);
Task<bool> t3 = Task.Factory.StartNew<bool>(() => Find(paramG, paramH);
t0.ContinueWith(_ =>
{
if (t0.Result)
tcs.TrySetResult(t0.Result);
});
t1.ContinueWith(_ =>
{
if (t1.Result)
tcs.TrySetResult(t1.Result);
});
t2.ContinueWith(_ =>
{
if (t2.Result)
tcs.TrySetResult(t2.Result);
});
t3.ContinueWith(_ =>
{
if (t3.Result)
tcs.TrySetResult(t3.Result);
});
t4.ContinueWith(_ =>
{
if (t4.Result)
tcs.TrySetResult(t4.Result);
});
tcs.Task.Wait();
return tcs.Task.Result;
当任何任务返回true
时,它可以正常工作,但正如前面的答案中所注意到的那样:
当所有任务都返回false时,这个棘手的位置会注意到... .NET 4.5通过创建另一个任务可以相当容易 Task.WhenAll
所以我尝试使用Task.WhenAll
,但我不想正确使用它...
我尝试过类似的东西:
tcs.Task.Wait(); // stays block here when all tasks return false
Task tr = Task.WhenAll(new Task[] { t0, t1, t2, t3, t4 });
if (tr.IsCompleted)
return false;
else
return tcs.Task.Result;
感谢您的帮助
答案 0 :(得分:5)
你想要等到你完成的两个任务之一,那就是Task.WaitAny()
的用途:
Task tr = Task.WhenAll(new Task[] { t0, t1, t2, t3, t4 });
Task.WaitAny(tcs.Task, tr);
if (tcs.Task.IsCompleted)
return tcs.Task.Result;
return false;
这也修复了代码中的竞争条件:tr.IsCompleted
可能是true
,即使某个任务返回true
,因为所有任务都可以同时完成。< / p>
作为替代方案,如果您不想阻止,可以使用Task.WhenAny()
。
但是,由于您使用的是.Net 4.5,因此您可以将await
与Interleaved()
method, which orders the tasks as they complete一起使用:
async Task<bool> AnyTrue(IEnumerable<Task<bool>> tasks)
{
foreach(var bucket in Interleaved(tasks))
{
if (await await bucket)
return true;
}
return false;
}
答案 1 :(得分:2)
要查看结果false
,您可以使用
if (!task.Result)
{
// Do stuff...
}
这将检查布尔结果是否为false。为了更完整,你可以做类似
的事情asyncTask.ContinueWith(task =>
{
// Check task status.
switch (task.Status)
{
case TaskStatus.RanToCompletion:
if (asyncTask.Result)
{
// returned true.
}
else
{
// returned false
}
break;
default:
break;
}
}
我希望这会有所帮助。