Flo*_*ian 2 c# task task-parallel-library
我有一些返回布尔值的任务。我只想等到任何任务首先返回 True 时。是否可以 ?
我的第一个想法是使用 CancellationTokenSource 但这不是一个好主意,因为当我调用 Task.WaitAll 方法时它会抛出异常。
第二种选择是使用我传入的 bool 参数,如果为真,则直接返回。它有效,但性能不佳:
bool isFound = false;
Task<bool> t0 = Task.Factory.StartNew<bool>(() => Find(paramA, paramB, ref isFound));
Task<bool> t1 = Task.Factory.StartNew<bool>(() => Find(paramC, paramD, ref isFound));
Task<bool> t2 = Task.Factory.StartNew<bool>(() => Find(paramE, paramF, ref isFound));
Task<bool> t3 = Task.Factory.StartNew<bool>(() => Find(paramG, paramH, ref isFound));
Task.WaitAll(new Task[] { t0, t1, t2, t3, t4 });
return t0.Result | t1.Result | t2.Result | t3.Result | t4.Result;
Run Code Online (Sandbox Code Playgroud)
并在方法中:
private static bool Find(int[,] m1, int[,] m2, ref bool isFound)
{
if (isFound)
return false;
// Do work...
}
Run Code Online (Sandbox Code Playgroud)
编辑 :
作为预先确定的答案,我使用了TaskCompletionSource<bool>now :
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;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当所有任务都返回 false 时,什么也没有注意到,这是正常的。但是我不知道如何使用该WhenAll方法。我试图添加这个:
tcs.Task.Wait();
Task tr = Task.WhenAll(new Task[] { t0, t1, t2, t3, t4 });
if (tr.IsCompleted)
return false;
else
return tcs.Task.Result;
Run Code Online (Sandbox Code Playgroud)
但它不起作用:(
一种选择是创建TaskCompletionSource您想要的任何类型(以确定结果,如果需要)。然后为每个任务添加一个延续,TaskCompletionSource.TrySetResult如果结果为真则调用。
然后就等着吧TaskCompletionSource.Task。它避免了您必须Task.WaitAny重复调用、检查结果等。
棘手的一点是注意到当所有任务都返回 false 时……在 .NET 4.5 中,这将相当容易,通过通过创建另一个任务Task.WhenAll- 然后您只需等待第一个{ success, all failed }完成。
| 归档时间: |
|
| 查看次数: |
5011 次 |
| 最近记录: |