以下方法之间有什么区别吗?一个比另一个好吗?
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);
}
答案 0 :(得分:7)
有两个实际差异:
async-await
使用的状态机机制。这将对性能产生次要正面影响。async
时,任何异常都存储在返回的任务中(来自异步部分和同步部分),并且仅在等待(或等待)任务时抛出。当它不是async
时,同步部分的异常就像任何其他方法一样。我的建议:使用第二个来提高性能,但请留意异常和错误。
显示差异的示例:
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
答案 1 :(得分:5)
await
的第一个方法将导致编译器创建状态机,因为一旦the await
关键字被命中,该方法将返回给调用者,一旦等待的部分完成,它具有从它停止的地方恢复。
但是,由于等待后你没有做任何事情(没有延续),所以不需要那个状态机。
在这种情况下,第二种方法是首选,您可以省略async
关键字,因为您没有等待任何事情
答案 2 :(得分:5)
首先,我认为您的示例中的代码不会编译。您需要从SendAsync2中删除“async”关键字。
如果你这样做,那么这些方法可以互换使用,所以不,这种情况没有区别。我更喜欢没有异步/等待的那个。
然而,有些情况似乎没有区别,但区别在于细节。例如,考虑以下代码:
async Task<X> Get()
{
using (something)
{
return await GetX();
}
}
如果您要将其更改为:
Task<X> Get()
{
using (something)
{
return GetX();
}
}
然后using
块不再保护封装在x中的执行,并且something
将比第一种情况更早地处置。例如,当something
是实体框架上下文时,这很重要。
return await
块中的try
也是如此。