Async & await всегда возвращает «Ожидание завершения» - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть приложение, в котором я использую Async и Await при вызове веб-службы отдыха.Когда я запускаю свои модульные тесты, я не могу получить какой-либо правильный ответ, хотя я использую await.Это асинхронный метод:

public async Task<Response> SendEmail(string apiKey, string senderEmail, string senderName, string recipientEmail, string recipientName, string subject, string content, bool html)
{
    var client = new SendGridClient(apiKey);
    var from = new EmailAddress(senderEmail, senderName);
    var to = new EmailAddress(recipientEmail, recipientName);
    var msg = MailHelper.CreateSingleEmail(from, to, subject, html ? null : content, html ? content : null);
    var response = await client.SendEmailAsync(msg);

    return response;
}

Вызывающий метод выглядит следующим образом:

public static object SendEmail(string apiKey, string senderEmail, string senderName, string recipientEmail, string recipientName, string subject, string content, bool html)
{
    EmailHandler emailHandler = new EmailHandler();
    var response =  emailHandler.SendEmail(apiKey, senderEmail, senderName, recipientEmail, recipientName, subject, content, html);

    return response;
}

Теперь, если я поставлю точку останова на ответ возврата в вызывающей функции, я смогу увидеть объекткоторый имеет статус = "Ожидание активации" и Результат = "Еще не вычислено".Из того, что я смог собрать, вызов .Reult для возвращенного объекта должен заставить его работать синхронно и возвращать результат.(Например, код состояния запроса, например 200).

Что мне здесь не хватает?Почему он не ждет, пока не закончится?

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

async-await - это просто ключевые слова, которые говорят компилятору компилировать ваш код как реализацию IAsyncStateMachine, а также ожидают его завершения, оба эти слова должны использоваться вместе, чтобы это работало, и они работают только надTask объекты.Task представляет часть выполняемой работы.

Вы должны пометить ваш метод SendEmail как async, изменить тип возвращаемого значения на Task<object> и await ваш emailHandler.SendEmail вызов.

Итог: если вы идете async, то вы должны пройти async до конца вверх и await в некоторых или многих точкахиначе вы начинаете смотреть на синхронный запуск асинхронного кода, который является своего рода стрельбой в ногу.

public static async Task<object> SendEmail(string apiKey, string senderEmail, string senderName, string recipientEmail, string recipientName, string subject, string content, bool html)
{
    EmailHandler emailHandler = new EmailHandler();
    var response = await emailHandler.SendEmail(apiKey, senderEmail, senderName, recipientEmail, recipientName, subject, content, html);

    return response;
}

Как всегда, Стивен Клири является отличным источником знаний async.

0 голосов
/ 22 февраля 2019

Мне кажется, вы ожидаете, что SendEmail будет синхронным.Вы можете дождаться завершения асинхронного метода в SendEmail следующим образом:

public static Response SendEmail(string apiKey, string senderEmail, string senderName, string recipientEmail, string recipientName, string subject, string content, bool html)
{
    EmailHandler emailHandler = new EmailHandler();
    var responseTask =  emailHandler.SendEmail(apiKey, senderEmail, senderName, recipientEmail, recipientName, subject, content, html);
    responseTask.Wait(); // Wait for the task to complete

    return responseTask.Result;
}
0 голосов
/ 22 февраля 2019

Это потому, что

var response =  emailHandler.SendEmail(apiKey, senderEmail, senderName, recipientEmail, recipientName, subject, content, html);

инициирует задачу, а ваш вызывающий объект (публичный статический объект SendEmail) не ожидает этой задачи.

Крис Пратт написал хороший блог с помощью асинхронного помощника для запуска синхронизации асинхронных методов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...