Если я напишу метод, который просто обертывает метод async, например:
public async Task WrapMethodAsync()
{
using(var smtpClient = new SmtpClient())
{
await smtpClient.SendMailAysnc(new MailMessage());
}
}
Это то же самое, что делать следующее:
public Task WrapMethodAsync()
{
using(var smtpClient = new SmtpClient())
{
return smtpClient.SendMailAysnc(new MailMessage());
}
}
Или последнее не работает асинхронно?
В этом точном сценарии два случая чрезвычайно различны из-за using
области.
В первом случае вы ожидаете (асинхронно) для SendMailAysnc
операции SendMailAysnc
перед удалением клиента, в то время как в другом случае вы этого не делаете, вы будете распоряжаться клиентом, пока операция все еще выполняется.
В общем случае, когда нет разницы в общем поведении. Например, это:
public async Task Run()
{
throw new Exception("stored");
await Task.Delay(-1);
}
VS это:
public Task Run()
{
throw new Exception("thrown");
return Task.Delay(-1);
}
Разница заключается в том, что async
методе имеет небольшую нагрузку всего async
механизма ( в том числе конечного автомата) в то время как non- async
Метод задачи возвращающего имеет различные семантики исключений, как исключения выбрасываются непосредственно, а не хранящиеся в возвращаемой задаче.
Первый фрагмент удаляет клиента после отправки почты, последний удаляет клиента после его отправки, но до его завершения. Предполагая, что клиент не должен быть удален во время отправки сообщений, это означает, что первое решение очень проблематично.
Кроме того, семантика обработки ошибок отличается; исключения при построении Task
в первом фрагменте приведут к тому, что метод выбрасывает исключение, тогда как во втором фрагменте они возвращают задачу возврата, помеченную как " Faulted
соответствующим набором исключений.
SmtpClient
конструктор (илиMailMessage
конструктора, или в началеSendMailAsync
метода), в первом случае вы получите неисправную задачу; во втором случае вы сразу получите исключение.