【问题标题】:How to use Task.WhenAll properly如何正确使用 Task.WhenAll
【发布时间】:2013-10-07 21:50:39
【问题描述】:

按照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 这将相当容易,通过创建另一个任务 任务.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;

感谢您的帮助

【问题讨论】:

  • 即使所有任务都返回false,如何使用Task.WhenAll获取结果?

标签: c# task async-await


【解决方案1】:

您想等到完成两项任务之一,这就是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,因为所有任务可以同时完成。

如果您不想屏蔽,也可以使用Task.WhenAny()

但由于您使用的是 .Net 4.5,您不妨将awaitInterleaved() 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;
}

【讨论】:

  • 谢谢你的回答...我试试看! :)
【解决方案2】:

要在false 时检查结果,您可以使用

if (!task.Result)
{ 
    // Do stuff...
}

这将检查布尔结果是否为假。为了更完整,您可以执行类似的操作

asyncTask.ContinueWith(task =>
{
    // Check task status.
    switch (task.Status)
    {
        case TaskStatus.RanToCompletion:
            if (asyncTask.Result)
            {
                // returned true.
            }
            else
            {
                // returned false
            }
            break;
        default:
            break;
    }
}

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 2015-01-30
    • 2014-09-08
    • 2015-09-10
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多