C# 等待已完成的任务时会发生什么情况?
当我构造一个我拥有的类的实例时,我想触发一个令牌更新函数(C# 等待已完成的任务时会发生什么情况?,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,当我构造一个我拥有的类的实例时,我想触发一个令牌更新函数(async方法),并让它在后台运行(我保留对返回的任务的引用) 稍后,当用户触发请求时,我希望等待任务 让我们假设任务在1秒后完成,用户在2秒后触发请求(这意味着任务完成) 处理用户请求的方法waitsTask,它会立即得到值吗?毕竟,任务已经完成并保存了该值。您将直接输入结果。任务完成后,其result属性将包含结果并保留它 处理用户请求的方法等待该任务,它会立即得到值吗 对。你可以认为它是懒惰的,如果你等待一个已经完成的任务,它会立即
async
方法),并让它在后台运行(我保留对返回的任务的引用)
稍后,当用户触发请求时,我希望等待任务
让我们假设任务
在1秒后完成,用户在2秒后触发请求(这意味着任务
完成)
处理用户请求的方法wait
sTask
,它会立即得到值吗?毕竟,任务
已经完成并保存了该值。您将直接输入结果。任务完成后,其result属性将包含结果并保留它
处理用户请求的方法等待该任务,它会立即得到值吗
对。你可以认为它是懒惰的,如果你等待一个已经完成的任务,它会立即返回。您可以在不同的线程上等待它几次,它只有在得到结果(或出现故障)后才会返回
正是因为这个原因,才添加了一个细节。您可以等待
此操作,它将立即返回已完成的成功任务。您可以使用task创建已完成的任务。FromResult(value)并等待:
var result = await Task.FromResult(5);
Debug.Assert(result == 5);
例如,如果您有一个方法可以返回缓存数据,但第一次需要异步获取数据,那么这将非常有用
因此,是的,您可以等待已经完成的任务。虽然OP没有提到ValueTask
,但我添加此答案以包括ValueTask
,因为它是在最初提出此问题后添加的
- 关于
任务
和任务
,正如其他人所指出的,您可以
多次等待任务
(或完成任务
)。如果任务已完成
运行到完成,它会立即返回
- 但是,如果您正在使用
ValueTask
或ValueTask
,则不能再等待了
不止一次ValueTask
和ValueTask
是在.NET中引入的
Core 2.0和用于避免/最小化性能敏感区域的内存分配
正如Stephen Toub在Dotnet博客上所说:
但是,因为ValueTask和ValueTask可能包装为可重用的
对象上,实际上存在显著的约束
当与任务和任务进行比较时,是否有人
偏离只等待他们的理想路径。总的来说
绝对不能对ValueTask执行以下操作/
ValueTask:
- 多次等待ValueTask/ValueTask。这个
基础对象可能已被回收,并已被使用
另一个手术。相反,一项任务/任务永远不会
从完整状态过渡到不完整状态,因此您可以等待
根据需要多次,每次都会得到相同的答案
时间李>
- 同时等待ValueTask/ValueTask。这个
基础对象希望只使用来自
一次只有一个消费者,并试图同时等待它
很容易引入竞争条件和微妙的程序错误。它是
也只是上述不良操作的一个更具体的例子:“等待
ValueTask/ValueTask多次。”相比之下,任务/
任务不支持任意数量的并发等待李>
- 使用
.GetAwaiter().GetResult()当操作尚未完成时。这个
IValueTaskSource/IValueTaskSource实施不需要
支持阻塞,直到操作完成,可能不会,所以
这种操作本质上是一种竞争条件,不太可能
按来电者的意愿行事。相比之下,任务/任务
请启用此选项,在任务完成之前阻止调用方李>
如果您有ValueTask或ValueTask,并且需要执行以下操作之一:
这些东西,您应该使用.AsTask()来获取任务
然后对生成的任务对象进行操作。在那之后,你
不应再与该ValueTask/ValueTask交互
简短的规则是:对于ValueTask或ValueTask,您
应该直接等待它(可以选择使用
.ConfigureAwait(false))或直接对其调用AsTask(),然后
不要再使用它,例如
以及来自ValueTask
和ValueTask
的MSDN文档:
以下操作不应在机器上执行
ValueTask实例:
- 多次等待该实例
- 多次调用AsTask
- 在操作尚未完成时使用.Result或.GetAwaiter().GetResult(),或多次使用它们
- 使用这些技术中的多个来使用实例
如果执行上述任一操作,则结果未定义。
您可以阅读更多关于ValueTask
和ValueTask
和的信息。是的,它会立即返回结果。@MatthewWatson为什么不写它作为答案?我本来会接受你的答案的。我想,它实际上不够长或不够详细,不足以作为答案来写。请注意,如果你多次调用wait
,它将每次返回它,如果它不是值,它将通过引用返回它。我不确定实际任务是否100%相同,但我会这样假设。