async 方法是否应该始终调用 await,如果不是,这意味着什么?
Should async method always call await, if not what is the implication?
在这个例子中,
private async void Button1_Click(object sender, EventArgs e)
{
if (condition) await Task.Run(Foo);
}
private void Foo()
{
Thread.Sleep(5000);
}
有时条件为假,异步方法什么都不等待。但是考虑这个例子,
private async void Button1_Click(object sender, EventArgs e)
{
await Task.Run(Foo);
}
private void Foo()
{
if (condition) Thread.Sleep(5000);
}
始终等待该方法,即使条件为假。我想知道幕后发生了什么,如果一个比另一个更可取,我的意思是 objectively 如果有编译器优化使一个比另一个更可取。假设可以从任何线程检查条件,并且对性能的影响非常小。
似乎当条件检查被推迟时,总是有一个任务在等待,但是当它在处理程序中为 false 时,我的情况接近于异步方法缺少 await 运算符的情况,大约编译器警告我。所以它同时感觉是错误的和正确的。希望有人可以 objective 阐明这个问题。
方法上的 async
关键字仅向编译器指示,方法内的代码应转换为 state-machine,并在 await
处进行状态转换。
据我所知,唯一的 down-side 技术 async
方法不 await
任何东西,是 await
引入的少量开销=18=]。它应该没有负面影响,除了非常小的性能影响和一点点 memory-pressure,这在您的场景中很可能会被忽略。
Should async method always call await, if not what is the implication?
正如我所描述的 on my blog,async
方法总是同步开始执行,就像任何其他方法一样。 await
事情可能变得异步。
如果在没有 await
的地方采用代码路径(或者如果等待的任务已经完成),则该方法同步完成,并且 returns 一个 already-completed 任务它的来电者。这在实践中不是问题,因为“*Async”的意思是“可能是异步的”,而不是“必须是异步的”。
在这个具体示例中,您使用的是 async void
,但如果这是一个被多次调用的 async Task
方法,在这种情况下我建议考虑返回 ValueTask
相反,这会在同步完成时为 Task
节省一些内存分配。
在您的特定情况下,Thread.Sleep(5000)
不是暂停执行的最佳方式。 Thread.Sleep(5000)
是旧的 API,它 阻塞 给定时间(5000 毫秒)的执行线程。 那是什么意思?这意味着该线程将无法用于其他任务。比方说,给定你的计算机 CPU 输出,你总共有 4 个线程,你将其中的 1 个锁定了 5000 毫秒 - 这 真的 很糟糕,尤其是如果它是一个 Web 应用程序必须处理并发 API 请求。用什么代替? await Task.Delay(5000)
它将“挂起”给定时间的执行,但线程将返回线程池并将可用于其他任务。
现在更接近你的问题了。将 non-asynchronous 代码包装到 Task
并等待 不会做任何事情。 Async/await 专为 I/O 操作而设计,专门用于不阻塞等待 I/O 完成的线程。将代码包装到 Task
和 not waiting - 基本上是“即发即忘”,这意味着您的执行线程可能会继续执行下一个块而无需等待您的 Task
方法来完成。为什么我说 可能 是因为如果 Task
中的代码包装器足够快它会同步工作
在这个例子中,
private async void Button1_Click(object sender, EventArgs e)
{
if (condition) await Task.Run(Foo);
}
private void Foo()
{
Thread.Sleep(5000);
}
有时条件为假,异步方法什么都不等待。但是考虑这个例子,
private async void Button1_Click(object sender, EventArgs e)
{
await Task.Run(Foo);
}
private void Foo()
{
if (condition) Thread.Sleep(5000);
}
始终等待该方法,即使条件为假。我想知道幕后发生了什么,如果一个比另一个更可取,我的意思是 objectively 如果有编译器优化使一个比另一个更可取。假设可以从任何线程检查条件,并且对性能的影响非常小。
似乎当条件检查被推迟时,总是有一个任务在等待,但是当它在处理程序中为 false 时,我的情况接近于异步方法缺少 await 运算符的情况,大约编译器警告我。所以它同时感觉是错误的和正确的。希望有人可以 objective 阐明这个问题。
方法上的 async
关键字仅向编译器指示,方法内的代码应转换为 state-machine,并在 await
处进行状态转换。
据我所知,唯一的 down-side 技术 async
方法不 await
任何东西,是 await
引入的少量开销=18=]。它应该没有负面影响,除了非常小的性能影响和一点点 memory-pressure,这在您的场景中很可能会被忽略。
Should async method always call await, if not what is the implication?
正如我所描述的 on my blog,async
方法总是同步开始执行,就像任何其他方法一样。 await
事情可能变得异步。
如果在没有 await
的地方采用代码路径(或者如果等待的任务已经完成),则该方法同步完成,并且 returns 一个 already-completed 任务它的来电者。这在实践中不是问题,因为“*Async”的意思是“可能是异步的”,而不是“必须是异步的”。
在这个具体示例中,您使用的是 async void
,但如果这是一个被多次调用的 async Task
方法,在这种情况下我建议考虑返回 ValueTask
相反,这会在同步完成时为 Task
节省一些内存分配。
在您的特定情况下,Thread.Sleep(5000)
不是暂停执行的最佳方式。 Thread.Sleep(5000)
是旧的 API,它 阻塞 给定时间(5000 毫秒)的执行线程。 那是什么意思?这意味着该线程将无法用于其他任务。比方说,给定你的计算机 CPU 输出,你总共有 4 个线程,你将其中的 1 个锁定了 5000 毫秒 - 这 真的 很糟糕,尤其是如果它是一个 Web 应用程序必须处理并发 API 请求。用什么代替? await Task.Delay(5000)
它将“挂起”给定时间的执行,但线程将返回线程池并将可用于其他任务。
现在更接近你的问题了。将 non-asynchronous 代码包装到 Task
并等待 不会做任何事情。 Async/await 专为 I/O 操作而设计,专门用于不阻塞等待 I/O 完成的线程。将代码包装到 Task
和 not waiting - 基本上是“即发即忘”,这意味着您的执行线程可能会继续执行下一个块而无需等待您的 Task
方法来完成。为什么我说 可能 是因为如果 Task
中的代码包装器足够快它会同步工作