C# 火灾和遗忘的异步/等待方法
假设我在winforms应用程序中有以下代码C# 火灾和遗忘的异步/等待方法,c#,winforms,asynchronous,async-await,C#,Winforms,Asynchronous,Async Await,假设我在winforms应用程序中有以下代码 private async Task<decimal> DivAsync(int a, int b) { await TaskEx.Delay(2000); return a / b; } private async Task DivAsyncWithErrorHandling(int a, int b) { try {
private async Task<decimal> DivAsync(int a, int b)
{
await TaskEx.Delay(2000);
return a / b;
}
private async Task DivAsyncWithErrorHandling(int a, int b)
{
try
{
await DivAsync(a, b);
}
catch (DivideByZeroException)
{
Debug.WriteLine("DivAsync({0}, {1}) failed", a, b);
}
}
private void button1_Click(object sender, EventArgs e)
{
DivAsyncWithErrorHandling(5, 0);
}
private void button2_Click(object sender, EventArgs e)
{
TaskEx.Run(() => DivAsyncWithErrorHandling(5, 0));
}
private async void button3_Click(object sender, EventArgs e)
{
await DivAsyncWithErrorHandling(5, 0);
await SomeThingElse();
}
执行任务。运行,因为它更清楚正在发生的事情,并且是推荐的方法 “当不需要对任务的创建和调度进行更多控制时,运行方法是创建和启动任务的首选方法。” 资料来源: 如果您的工作受CPU限制,并且您关心响应性,请使用async和Wait,但使用Task.Run在另一个线程上生成工作
来源:执行任务。运行,因为它更清楚正在发生的事情,并且是推荐的方法 “当不需要对任务的创建和调度进行更多控制时,运行方法是创建和启动任务的首选方法。” 资料来源: 如果您的工作受CPU限制,并且您关心响应性,请使用async和Wait,但使用Task.Run在另一个线程上生成工作
来源:如何使
divasync处理returnvoid
?我明白这句话是说“你永远不能等待这个方法”,但如果这个方法,在这种情况下,不应该被等待,而是应该被激发并忘记它被调用的任何地方,那么这就是正确的解决方案。@LasseV.Karlsen它可能被等待(参见按钮3\u点击)但不是在我的代码库中的所有地方。您的目标是不受支持的.NET版本吗?所有支持的版本都有Task.Run
,而不是TaskEx.Run
作为差异-DivAsync
不会异步运行,直到遇到第一个wait
button2\u-Click
是完全激发并忘记,而button1\u-Click
不是。在这种情况下,方法的作用很重要。它是IO还是CPU绑定?对于IO工作,例如调用多个web服务,您可以只调用该方法。如果在第一次IO之前它包含大量CPU工作,那么您需要Task.RunHow如何使div处理
返回void
?我明白这句话是说“你永远不能等待这个方法”,但如果这个方法,在这种情况下,不应该被等待,而是应该被激发并忘记它被调用的任何地方,那么这就是正确的解决方案。@LasseV.Karlsen它可能被等待(参见按钮3\u点击)但不是在我的代码库中的所有地方。您的目标是不受支持的.NET版本吗?所有支持的版本都有Task.Run
,而不是TaskEx.Run
作为差异-DivAsync
不会异步运行,直到遇到第一个wait
button2\u-Click
是完全激发并忘记,而button1\u-Click
不是。在这种情况下,方法的作用很重要。它是IO还是CPU绑定?对于IO工作,例如调用多个web服务,您可以只调用该方法。如果在第一次IO之前它包含大量CPU工作,那么您需要Task.RunIt不是“推荐的方法”。文件上不是这么说的。您复制的代码段来自比较冷任务和热任务的段落。问题是是否使用wait
。有些差异与controlFair无关,但仍然建议使用它,因为Task.Run在另一个线程中启动工作,从而释放调用(UI)线程,我想这就是重点。与什么相比?问题不是如何在后台运行某些东西。OP发布的所有选项都已使用任务。与不使用“wait”调用异步方法相比,使用不同的defaults也是一样的。Task.Run是相同的,在这种情况下,它应该被用来保留功能并遵循异步/等待控制流,正如Jürgen所希望的那样。事实上,可以说,建议的方法是不使用Task.Run,而使用后缀为async
的方法返回任务。该方法的实现者明确地告诉您该方法已经是异步的,为什么要假设这是一个谎言?为什么要将任务包装到另一个任务中,并且必须调用.Result.Result
?如果您是实现者,那么在异步调用不是“推荐方法”之前,您需要确保没有昂贵的调用。文件上不是这么说的。您复制的代码段来自比较冷任务和热任务的段落。问题是是否使用wait
。有些差异与controlFair无关,但仍然建议使用它,因为Task.Run在另一个线程中启动工作,从而释放调用(UI)线程,我想这就是重点。与什么相比?问题不是如何在后台运行某些东西。OP发布的所有选项都已使用任务。与不使用“wait”调用异步方法相比,使用不同的defaults也是一样的。Task.Run是相同的,在这种情况下,它应该被用来保留功能并遵循异步/等待控制流,正如Jürgen所希望的那样。事实上,可以说,建议的方法是不使用Task.Run,而使用后缀为async
的方法返回任务。该方法的实现者明确地告诉您该方法已经是异步的,为什么要假设这是一个谎言?为什么要将任务包装到另一个任务中,并且必须调用.Result.Result
?如果您是实现者,那么在异步调用之前,您需要确保没有昂贵的调用
private DivAsyncWithErrorHandlingOld(int a, int b, Action after = null)
{
Task.Factory.StartNew(() =>
{
try
{
Div(a, b);
}
catch (DivideByZeroException)
{
Debug.WriteLine("DivAsync({0}, {1}) failed", a, b);
}
after?.Invoke();
});
}