lov*_*ing 1 c# wpf asynchronous async-await
我正在构建一个 WPF 应用程序并调用这个自定义事件。这里的问题是我应该ConfigureAwait(false)到处打电话吗?正如你现在看到的,我调用了 2 次。甚至在第二个方法中 3 次,ConfigureAwait(false)在同一行中使用双倍。
// First approach
void RaiseProcessEvent(object sender, EventArgs e)
{
Task.Run(async () => await APIManager.GetInstance.ProcessMethod()).ConfigureAwait(false);
}
// Second approach
void RaiseProcessEvent(object sender, EventArgs e)
{
Task.Run(async () => await APIManager.GetInstance.ProcessMethod().ConfigureAwait(false)).ConfigureAwait(false);
}
// This function is in a singleton class
public async Task ProcessMethod()
{
var result = await GetInstance.GetFinalResultFromHttpClientAsync().ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是我应该在任何地方都调用 ConfigureAwait(false) 吗?
一般来说,ConfigureAwait(false)如果方法不需要在其调用上下文上恢复,则应使用。是否使用的决定ConfigureAwait(false)应该在每个方法的基础上做出,并且应该用于await该方法中的每一个,或者不应该用于await该方法中的每一个。
更实用的是,ConfigureAwait(false)应该在旨在重用的代码中使用,可能在不同的上下文中。应用程序代码很少需要使用ConfigureAwait(false),尽管我曾遇到过需要防止大量延续中断 UI 线程的情况。
正如你现在看到的,我打了 2 次电话。甚至在同一行中使用 double configure(false) 的第二种方法进行 3 次。
在这些情况下,ConfigureAwait(false)是没有意义的。原因如下:
//first approach
Task.Run(async () => await APIManager.GetInstance.ProcessMethod()).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
ConfigureAwait配置一个await. 它不配置任务。由于Task.Run从不awaited返回的任务,因此ConfigureAwait什么也不做。
//second approach
Task.Run(async () => await APIManager.GetInstance.ProcessMethod().ConfigureAwait(false)).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
的false部分ConfigureAwait(false)是continueOnCapturedContext参数。所以ConfigureAwait(false)说“这个方法不需要在捕获的上下文上继续”。但是在这种情况下,async委托正在线程池上运行(就是这样Task.Run做的),因此您知道无论如何都没有要捕获的上下文。
旁注 1:当Task.Run用于调用异步方法时,通常会省略async和await关键字。例如:Task.Run(() => APIManager.GetInstance.ProcessMethod());。所以这个ConfigureAwait(false)问题无论如何都没有实际意义,因为已经没有await了。
旁注 2:丢弃返回的任务Task.Run意味着代码正在执行即发即忘,这几乎总是一个可怕的错误。除此之外,这意味着任何异常都会被默默地吞下。几乎总是更好地使用await:
async void RaiseProcessEvent(object sender, EventArgs e)
{
await Task.Run(() => APIManager.GetInstance.ProcessMethod());
}
Run Code Online (Sandbox Code Playgroud)
现在有一个await用于从 返回的任务Task.Run,因此此时提出问题是合适的:这await应该使用ConfigureAwait(false)吗?这里的意见可能会有所不同,但我会说不,因为这显然是应用程序级代码(UI 事件处理程序),并且大多数开发人员会假设运行事件处理程序的代码将在 UI 线程上(即使await之前有那个方法)。因此,为了获得最大的可维护性,我不会ConfigureAwait(false)在 UI 事件处理程序方法中使用 a ,除非我出于性能原因必须添加它。