C# 异步方法中返回和等待任务之间的区别
下面的方法有什么不同吗?一个比另一个好吗C# 异步方法中返回和等待任务之间的区别,c#,.net,task-parallel-library,async-await,C#,.net,Task Parallel Library,Async Await,下面的方法有什么不同吗?一个比另一个好吗 public static async Task SendAsync1(string to, string subject, string htmlBody) { // ... await smtp.SendMailAsync(message); // No return statement } public static Task SendAsync2(string to, string subject, string htmlBody)
public static async Task SendAsync1(string to, string subject, string htmlBody) {
// ...
await smtp.SendMailAsync(message);
// No return statement
}
public static Task SendAsync2(string to, string subject, string htmlBody) {
// ...
return smtp.SendMailAsync(message);
}
此方法将从MVC控制器方法调用;例如:
public async Task<ActionResult> RegisterUser(RegisterViewModel model)
{
// ...
await Mailer.SendAsync(user.Email, subject, body);
return View(model);
}
公共异步任务注册器(RegisterViewModel模型)
{
// ...
wait Mailer.SendAsync(user.Email,subject,body);
返回视图(模型);
}
您的第一个方法是await
s,它将导致编译器创建一个状态机,因为一旦点击了await
关键字,该方法将返回给调用者,并且一旦等待的部分完成,它必须从停止的点恢复
但是,由于您在等待之后没有做任何事情(没有继续),因此不需要该状态机
在这种情况下,第二种方法是首选的,您可以从中省略
async
关键字,因为您没有等待任何东西您的第一种方法await
s将导致编译器创建一个状态机,因为一旦命中await
关键字,该方法将返回调用方,一旦等待的部分完成,它必须从它停止的地方重新开始
但是,由于您在等待之后没有做任何事情(没有继续),因此不需要该状态机
在这种情况下,第二种方法是首选的,您可以从中省略
async
关键字,因为您不需要等待任何东西。首先,我认为示例中的代码无法编译。您需要从SendAsync2中删除'async'关键字
如果你这样做,那么这些方法可以互换使用,所以在这种情况下没有区别。我更喜欢没有async/await的
然而,在有些情况下,似乎没有区别,但区别在于细节。例如,考虑这个代码:
async Task<X> Get()
{
using (something)
{
return await GetX();
}
}
异步任务Get()
{
使用(某物)
{
返回等待GetX();
}
}
如果要将此更改为:
Task<X> Get()
{
using (something)
{
return GetX();
}
}
Task Get()
{
使用(某物)
{
返回GetX();
}
}
然后using
块不再保护封装在x中的执行,并且某物将比第一种情况下更早地被处理。重要信息,例如当某物
是实体框架上下文时
这同样适用于return wait
insidetry
块。首先,我不认为您示例中的代码可以编译。您需要从SendAsync2中删除'async'关键字
如果你这样做,那么这些方法可以互换使用,所以在这种情况下没有区别。我更喜欢没有async/await的
然而,在有些情况下,似乎没有区别,但区别在于细节。例如,考虑这个代码:
async Task<X> Get()
{
using (something)
{
return await GetX();
}
}
异步任务Get()
{
使用(某物)
{
返回等待GetX();
}
}
如果要将此更改为:
Task<X> Get()
{
using (something)
{
return GetX();
}
}
Task Get()
{
使用(某物)
{
返回GetX();
}
}
然后using
块不再保护封装在x中的执行,并且某物将比第一种情况下更早地被处理。重要信息,例如当某物
是实体框架上下文时
在try
块内的return wait
也是如此。有两个实际区别:
第二个选项不会创建允许使用async wait
的状态机机制。这将对绩效产生轻微的积极影响
异常处理会有点不同。将方法标记为async
时,所有异常都存储在返回的任务中(来自异步部分和同步部分),并且仅在等待(或等待)任务时才会抛出。当它不是async
时,来自同步部分的异常就像在任何其他方法中一样
我的建议:使用第二种方法提高性能,但要注意异常和bug
一个显示差异的示例:
public static async Task Test()
{
Task pending = Task.FromResult(true);
try
{
pending = SendAsync1();
}
catch (Exception)
{
Console.WriteLine("1-sync");
}
try
{
await pending;
}
catch (Exception)
{
Console.WriteLine("1-async");
}
pending = Task.FromResult(true);
try
{
pending = SendAsync2();
}
catch (Exception)
{
Console.WriteLine("2-sync");
}
try
{
await pending;
}
catch (Exception)
{
Console.WriteLine("2-async");
}
}
public static async Task SendAsync1()
{
throw new Exception("Sync Exception");
await Task.Delay(10);
}
public static Task SendAsync2()
{
throw new Exception("Sync Exception");
return Task.Delay(10);
}
输出:
1-async
2-sync
有两个实际差异:
第二个选项不会创建允许使用async wait
的状态机机制。这将对绩效产生轻微的积极影响
异常处理会有点不同。将方法标记为async
时,所有异常都存储在返回的任务中(来自异步部分和同步部分),并且仅在等待(或等待)任务时才会抛出。当它不是async
时,来自同步部分的异常就像在任何其他方法中一样
我的建议:使用第二种方法提高性能,但要注意异常和bug
一个显示差异的示例:
public static async Task Test()
{
Task pending = Task.FromResult(true);
try
{
pending = SendAsync1();
}
catch (Exception)
{
Console.WriteLine("1-sync");
}
try
{
await pending;
}
catch (Exception)
{
Console.WriteLine("1-async");
}
pending = Task.FromResult(true);
try
{
pending = SendAsync2();
}
catch (Exception)
{
Console.WriteLine("2-sync");
}
try
{
await pending;
}
catch (Exception)
{
Console.WriteLine("2-async");
}
}
public static async Task SendAsync1()
{
throw new Exception("Sync Exception");
await Task.Delay(10);
}
public static Task SendAsync2()
{
throw new Exception("Sync Exception");
return Task.Delay(10);
}
输出:
1-async
2-sync
如果使用SendAsync1,可能在两个位置维护状态(通过异步/等待状态机制)的成本,但可能异步/等待状态机足够聪明,可以优化这一点…只是一个想法,但很有趣。如果使用SendAsync1,可能在两个位置维护状态(通过异步/等待状态机制)的成本,但是,也许异步/等待状态机足够聪明,可以对此进行优化…只是一个想法,但很有趣。使用/try-catch对潜在的gotcha环境进行了很好的观察!使用/try catch对潜在的gotcha周围环境进行了很好的观察!“不会创造国家机器的机械主义”-这是什么意思??你怎么知道的?你在哪里看到的?它就像隐形湖中的隐形人,我完全无法理解:(我的意思是身体上——发生了什么事?@monstro”不会创造