вызовы асинхронной библиотеки, полагающиеся друг на друга, и как с ними справиться?

это продолжение предыдущего вопроса, который я разместил Calling асинхронный метод с использованием Task.Run кажется неправильным?

Я думал, что код, написанный подрядчиком, был неправильным, но, следуя предоставленным ответам, я теперь задаюсь вопросом, виновата ли в этом библиотека. Эта библиотека предоставляет два метода, которые мне нужно использовать. Один возвращает «шаблон», а другой использует часть этого шаблона (во всяком случае, в моей реализации). Но оба являются async методами, возвращающими Tasks.

Чтобы объяснить, что в моей библиотеке есть методы:

public Task<TemplateInfo> TemplateInfo(TemplateInfoRequest request);
public Task<List<EmailResult>> SendMessageTemplate(SendMessageTemplateRequest request);

Мне нужно назвать это так:

public bool SendMessage()
{
  var template = TemplateInfo(...);
  var message = //use template to create message
  var sendResponse = SendMessageTemplate(message);

   return sendResponse.Count > 0;
}

Таким образом, второй вызов зависит от первого. Вот где асинхронность не имеет для меня смысла. Я не могу и не хочу запускать их параллельно. Я хочу запускать их последовательно. Я хочу, чтобы мой метод был синхронным.

В ответе на мой предыдущий вопрос также говорится:

Поскольку вы блокируете асинхронный метод (чего делать не следует), есть вероятность, что вы зайдете в тупик.

Итак, как мне получить доступ к этим async методам таким образом, чтобы они обрабатывались по очереди и возвращали синхронный результат, но не вызывали взаимоблокировок?


person Liam    schedule 16.09.2015    source источник
comment
Лиам, ты очень, очень, очень сбит с толку. Асинхронный не означает параллельный.   -  person Aron    schedule 16.09.2015
comment
@Aron: Асинхронность - это одна из форм параллелизма. Однако асинхронность — это не то же самое, что параллелизм.   -  person Stephen Cleary    schedule 17.09.2015


Ответы (1)


Асинхронный (обязательно) не означает параллельный.

Вы можете вызывать оба асинхронных метода последовательно, не выполняя их параллельно. Просто вызовите первую и ждите возвращенную задачу, а затем сделайте то же самое со второй.

var template = await TemplateInfo(...);
var message = //use template to create message
var sendResponse = await SendMessageTemplate(message);

Это по-прежнему полезно по сравнению с синхронным кодом, потому что, пока асинхронная операция «выполняется», нет необходимости в потоке, и поэтому ваши потоки могут работать над другими частями вашего приложения.

Если бы вы вызывали оба и только потом ждали возвращенных задач, вы (возможно) работали бы параллельно:

var templateTask = TemplateInfo(...);
var sendResponseTask = SendMessageTemplate(message);
await templateTask;
await sendResponseTask;
person i3arnon    schedule 16.09.2015
comment
Я предлагаю вам добавить немного о неблокирующем асинхронном вводе-выводе, чтобы прояснить преимущества последовательного асинхронного ввода-вывода. - person Aron; 16.09.2015
comment
Но чтобы добавить await, я должен пометить свой метод как async и вернуть Task, мне просто нужно одно значение синхронно. Я собирался просто использовать .Result, но тогда я блокирую асинхронность, не так ли? Чего я думал, что не должен был делать. Я добавил детали в вопрос. - person Liam; 16.09.2015
comment
Я полагаю, я запутался, в какой-то момент мне нужно перестать вызывать асинхронные методы и сделать их синхронными. Или еще, как я могу сообщить пользователю, что произошло. Итак, как мне изящно выйти из этого, не блокируя - person Liam; 16.09.2015
comment
@Liam Лучший вариант - асинхронный до самого верха. Это требует изменения вызовов методов до тех пор, пока вы не достигнете вершины (это может быть обработчик событий, Main и т. д.). Если вы не можете этого сделать по какой-то причине, тогда следующий вариант — вообще не использовать асинхронность и полностью использовать синхронный код. Если это не вариант (поскольку вы используете библиотеку с асинхронным API), то у вас нет другого варианта, кроме блокировки асинхронного кода, а затем попытаться убедиться, что это сделано безопасно. - person i3arnon; 16.09.2015