我有很多请求需要处理,其中一些可能会同步完成。我想收集所有立即可用的结果并尽早返回,同时等待其余的结果。
大致是这样的:
List<Task<Result>> tasks = new ();
List<Result> results = new ();
foreach (var request in myRequests) {
var task = request.ProcessAsync();
if (task.IsCompleted)
results.Add(task.Result); // or Add(await task) ?
else
tasks.Add(task);
}
// send results that are available "immediately" while waiting for the rest
if (results.Count > 0) SendResults(results);
results = await Task.WhenAll(tasks);
SendResults(results);
Run Code Online (Sandbox Code Playgroud)
我不确定依赖是否IsCompleted是一个坏主意;是否存在其结果不可信或可能再次变回false等情况?
task.Result同样,即使在检查之后使用是否会存在危险IsCompleted,是否应该始终选择await task?如果使用ValueTask代替呢Task?
我不确定依赖 IsCompleted 是否是一个坏主意;是否存在其结果不可信的情况...
如果您处于多线程上下文中,则当您检查 IsCompleted 时,IsCompleted 可能会返回 false,但此后它会立即完成。在像您正在使用的代码的情况下,发生这种情况的成本会非常低,所以我不会担心。
或者它可能会再次变回哪里
false等等?
不,一旦任务完成,它就不能取消完成。
task.Result检查后使用会不会有危险IsCompleted。
不,那应该总是安全的。
人们应该总是更喜欢吗
await task?
await当您没有特定原因做其他事情时,这是一个很好的默认值,但在许多用例中其他模式可能有用。您突出显示的用例是一个很好的示例,您希望返回已完成任务的结果而不等待所有任务。
正如 Stephen Cleary 在下面的评论中提到的,它可能仍然值得用来await维护预期的异常行为。您可能会考虑做类似这样的事情:
var requestsByIsCompleted = myRequests.ToLookup(r => r.IsCompleted);
// send results that are available "immediately" while waiting for the rest
SendResults(await Task.WhenAll(requestsByIsCompleted[true]));
SendResults(await Task.WhenAll(requestsByIsCompleted[false]));
Run Code Online (Sandbox Code Playgroud)
如果使用
ValueTask代替呢Task?
上述答案同样适用于这两种类型。