【发布时间】:2023-03-22 08:42:02
【问题描述】:
在我当前的项目中,我有一段代码,在将其简化为我遇到问题的地方后,看起来像这样:
private async Task RunAsync(CancellationToken cancel)
{
bool finished = false;
while (!cancel.IsCancellationRequested && !finished)
finished = await FakeTask();
}
private Task<bool> FakeTask()
{
return Task.FromResult(false);
}
如果我不等待就使用此代码,我最终还是会阻塞:
// example 1
var task = RunAsync(cancel); // Code blocks here...
... // Other code that could run while RunAsync is doing its thing, but is forced to wait
await task;
// example 2
var task = RunAsync(cancelSource.Token); // Code blocks here...
cancelSource.Cancel(); // Never called
在实际项目中,我并没有真正使用 FakeTask,而且通常会有一些我在里面等待的 Task.Delay,所以代码大部分时间并没有真正阻塞,或者只是有限的迭代次数。
然而,在单元测试中,我使用了一个模拟对象,它几乎可以做 FakeTask 所做的事情,所以当我想查看 RunAsync 是否响应它的 CancellationToken 被取消时,我被卡住了.
我发现我可以通过在 RunAsync 顶部添加例如 await Task.Delay(1) 来解决此问题,以强制它真正异步运行,但这感觉有点 hacky。有更好的选择吗?
【问题讨论】:
-
“类似这样的东西”。像这样足够您已经执行了您向我们展示的代码并遇到了同样的问题吗?
-
如果你没有任何异步,你将同步运行。阅读blog.slaks.net/2014-12-23/parallelism-async-threading-explained
-
只有当你有其他线程在运行时,异步才会做一些事情。如果你只有一个线程,那么它看起来就像阻塞一样。
-
@jdweng 如果这是真的,
async关键字在语言中将毫无用处。您所描述的是不是异步工作。 -
假设
cancel是一个CancellationToken,这段代码甚至不会编译。
标签: c# .net asynchronous async-await