【问题标题】:How to WhenAll when some tasks can be null?当某些任务可以为空时如何处理?
【发布时间】:2020-05-14 15:23:09
【问题描述】:

我想等待所有任务,但其中一些可以为空。就是这样的代码:

Task<MyType1> myTask1 = getData01Async();
Task<MyTyp2> myTask2 = null;
Task<MyType3> myTask3 = null;

if(myVariable == true)
{
    myTask2 = getData02Async();
}
else
{
    myTask3 = getData03Async();
}


wait Task.WhenAll(myTask1, myTask2, myTask3);

这个想法是,task1 总是存在的,但是 task2 和 task3 依赖于一个变量。所以我想并行运行所有任务并等待所有任务完成。如果一项任务为空,则将其视为已完成。

这段代码的问题是我在运行时得到一个空引用异常。

有什么方法可以做到这一点?或者我可以使用什么其他替代品?

【问题讨论】:

  • 如何将任务放入显式集合中并使用myTasks.Where(t =&gt; t!=null) 传递给Task.WhenAll
  • myTask1 ?? Task.CompletedTask
  • @ErnodeWeerd Task.CompletedTask 无法返回结果
  • @Fabjan meh,因为它们在Task&lt;T&gt; 意义上都是不同的T,所以没关系 - 这是params Task[] 过载,而Task.CompletedTask 绝对是@ 987654329@
  • @UweKeim 这正是我的想法,可以做一个很好的答案。

标签: c# async-await task-parallel-library


【解决方案1】:

只需过滤掉空任务:

await Task.WhenAll(new Task[] { task1, task2, task3 }.Where(i => i != null));

【讨论】:

  • 这是否意味着与我给出的答案不同?
  • @JSteward 我没有看你的答案(我的目的是让它简短,所以我没有挖掘长的),但是是的 - 它是一样的。
  • 很公平,只需要问一下
【解决方案2】:

好吧,根据您的场景,您可以分配已完成的任务或将它们放入数组/列表中,然后将此列表传递给WhenAll

Task<MyType1> myTask1 = getData01Async();
Task<MyType2> myTask2 = Task.FromResult((MyType2) null);
Task<MyType3> myTask3 = Task.FromResult((MyType3) null);

...

await Task.WhenAll(myTask1, myTask2, myTask3);

【讨论】:

  • 谢谢,这真的帮助了我。我有多个具有不同结果类型的任务,我不确定这些任务应该触发。有了这个解决方案,我仍然可以处理结果,而不必担心将所有内容添加到列表时通用任务返回的类型!
  • 唯一不明显的建议。谢谢!
  • 这是最好的解决方案。很容易做到 myTask = x != null ? MyAsync() : Task.CompletedResult 而不是创建数组并对其进行过滤。
【解决方案3】:

使用集合来跟踪不是null 的任务。然后将该列表传递给Task.WhenAll 方法,如下所示:

var tasks = new List<Task>();

Task<MyType1> myTask1 = getData01Async();
tasks.Add(myTask1);

Task<MyTyp2> myTask2 = null;
Task<MyType3> myTask3 = null;

if(myVariable == true)
{
    myTask2 = getData02Async();
    tasks.Add(myTask2);
}
else
{
    myTask3 = getData03Async();
    tasks.Add(myTask3);
}

await Task.WhenAll(tasks);

【讨论】:

    【解决方案4】:

    要建立在@UweKeim 建议的基础上,为什么不在将空任务传递给WhenAll 时简单地过滤掉它们。

    public async Task FilterNullTasks()
    {
        Task<string> myTask1 = Task.Delay(1000).ContinueWith(tsk => string.Empty);
        Task<int> myTask2 = null;
        Task<bool> myTask3 = null;
    
        await Task.WhenAll(new Task[]
        {
            myTask1, myTask2, myTask3
        }.Where(tsk => tsk != null));
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-15
      • 2013-05-12
      • 1970-01-01
      • 2018-01-08
      • 2023-04-02
      相关资源
      最近更新 更多