使用C#中的async/await - 如何处理多个任务且指定一个首选任务?

5
我有以下情景/要求:
我有两个任务,任务A和任务B,它们都返回相同类型的数据。如果任务A在完成时具有其结果中的数据,则需要返回任务A的结果,否则返回任务B的结果。
我正在尝试通过并行处理来进行性能优化,但不确定是否有比我所做的更好的方法。这似乎是很多代码来实现我的需求。
var firstSuccessfulTask = await Task.WhenAny(taskA, taskB);
if (firstSuccessfulTask != taskA)
{
    await taskA;
}

if (taskA.Result != null)
{
    return taskA.Result;
}

return await taskB;

3
为什么不直接调用 await taskA 而跳过 Task.WhenAny 的调用呢? - EJoshuaS - Stand with Ukraine
1个回答

12

按照您的需求编写代码。如果A不为空,返回A的结果;否则返回B的结果。

return await taskA ?? await taskB;

3
这样做不会启动任务B直到任务A完成,实际上使它们变成串行而不是并行吗? - Paul Gelardi
2
如果taskB是一个属性,当您调用该表达式时会启动该任务,那么是的。如果它是一个已经开始的本地/字段,则不是。考虑到命名惯例以及您反复使用了taskA(因此很明显并没有每次使用它时都创建新任务,因为如果您这样做,代码根本无法工作),这使得它非常清晰,它们都是变量,而不是计算新任务的表达式。如果它们确实是计算新任务的表达式,您需要先将其存储在本地变量中,然后再执行此操作。 - Servy
这很有道理。我并不知道当我调用异步方法时,任务B会立即开始执行 - 我以为它要等到有东西在等待它或者等待它完成才开始。 - Paul Gelardi
1
@PaulGelardi await 只是“等待”它完成,毕竟它不叫做 astart。但说真的,如果你尝试等待一个代表未启动线程的任务(通过调用 new Task(...) 而不是使用更正确的 Task.Run(...)),那么等待将永远不会返回,直到线程在其他地方启动并完成。 - Scott Chamberlain
1
@PaulGelardi:记住,await并不会创建异步操作。它描述了对现有异步任务涉及的控制流程的限制。这个限制是在等待之后的代码直到任务完成后才会执行 - Eric Lippert
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接