SmtpClient.SendMailAsync вызывает взаимоблокировку при возникновении определенного исключения

Я пытаюсь настроить подтверждение по электронной почте для веб-сайта ASP.NET MVC5 на основе примера AccountController из шаблона проекта VS2013. Я реализовалIIdentityMessageService с помощьюSmtpClientстараясь сделать его максимально простым:

public class EmailService : IIdentityMessageService
{
    public async Task SendAsync(IdentityMessage message)
    {
        using(var client = new SmtpClient())
        {
            var mailMessage = new MailMessage("[email protected]", message.Destination, message.Subject, message.Body);
            await client.SendMailAsync(mailMessage);
        }
    }
}

Код контроллера, который его вызывает, прямо из шаблона (выделен в отдельное действие, так как я хотел исключить другие возможные причины):

public async Task<ActionResult> TestAsyncEmail()
{
    Guid userId = User.Identity.GetUserId();

    string code = await UserManager.GenerateEmailConfirmationTokenAsync(userId);
    var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = userId, code = code }, protocol: Request.Url.Scheme);
    await UserManager.SendEmailAsync(userId, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");

    return View();
}

Однако я получаю странное поведение, когда не удается отправить почту, но только в одном конкретном случае, когда узел как-то недоступен. Пример конфигурации:

<system.net>
    <mailSettings>
        <smtp deliveryMethod="Network">
            <network host="unreachablehost" defaultCredentials="true" port="25" />
        </smtp>
    </mailSettings>
</system.net>

В этом случае запрос оказывается в тупике, никогда не возвращая клиенту ничего. Если сообщение не отправляется по какой-либо другой причине (например, хост активно отказывается от соединения), исключение обрабатывается нормально, и я получаю YSOD.

Глядя на журналы событий Windows, кажется, чтоInvalidOperationException генерируется примерно в тот же период времени с сообщением «Асинхронный модуль или обработчик завершены, пока асинхронная операция еще не завершена».; Я получаю то же сообщение в YSOD, если пытаюсь пойматьSmtpException в контроллере и вернутьViewResult в блоке улова. Так что я понимаюawaitВ любом случае операция не завершается.

Насколько я могу судить, я следую всем рекомендациям по асинхронизации / ожиданию, описанным в других публикациях на SO (например,HttpClient.GetAsync (...) никогда не возвращается при использовании await / async), в основном "используя async / await до конца". Я также пытался использоватьConfigureAwait(false)без изменений. Поскольку код блокируется только в том случае, если выдается конкретное исключение, я полагаю, что общий шаблон верен в большинстве случаев, но что-то происходит внутри, что делает его неправильным в этом случае; но так как я довольно новичок в параллельном программировании, я чувствую, что могу ошибаться.

Я что-то не так делаю? Я всегда могу использовать синхронный вызов (т.е.SmtpClient.Send()) в методе SendAsync, но кажется, что это должно работать как есть.

Ответы на вопрос(0)

Ваш ответ на вопрос