Возможно, где-то в Интернете был дан ответ на этот вопрос, но я просмотрел множество примеров и до сих пор не могу понять.
У меня есть Граница уровня обслуживания на основе синхронизации (например, метод «ProcessOrder»). В рамках этого метода он выполняет различные функции, некоторые из которых имеют асинхронные перегрузки, и имеет смысл использовать их, поскольку они оборачивают функции, связанные с вводом-выводом.
Однако мое замешательство является двукратным. Из того, что я прочитал:
- асинхронный код должен быть «полностью асинхронным»
- методы с пометкой async не должны возвращать void — это крайний случай для обработчиков событий, и
не обрабатывает всплывающие исключения
Итак, пример кода, показанный ниже (примечание: _publisher — это оболочка для Azure QueueClient, имеющая методы асинхронной отправки):
Код: Выделить всё
public void ProcessOrder()
{
// other stuff...
_publisher.PublishAsync(new ItemOrderedEvent()
{
MessageId = Guid.NewGuid(),
IsDurable = true,
}).Wait();
}
Похоже, что это не соответствует правилу «полная асинхронность», и в Интернете есть предупреждения о взаимоблокировках и т. д. из-за исчерпания пула потоков при высоких нагрузках. об этом шаблоне, но код типа:
Код: Выделить всё
public async void ProcessOrder()
{
// other stuff...
await _publisher.PublishAsync(new ItemOrderedEvent()
{
MessageId = Guid.NewGuid(),
IsDurable = true,
});
}
Нарушает правило «методы, отмеченные асинхронным кодом, не должны возвращать void» и не обрабатывает исключения, поскольку, насколько я понимаю, нет контекста задачи, который мог бы вернуть их обратно из асинхронного кода. метод. Примечание. Это граница службы: вызывающий код может быть пользовательским интерфейсом в ответ на сообщение MSMQ, вызов веб-службы и т. д., поэтому я не хочу, чтобы «реализация» вызова службы просачивалась выше. В текущем контексте, IMO, имеет смысл использовать только вызов синхронизации.
Метод издателя определяется как:
Код: Выделить всё
public async Task PublishAsync(IMessageBusMessage message)
{
// do azure stuff
var _queue = QueueClient.CreateFromConnectionString(connectionString, "ItemOrdered");
await _queue.SendAsync(message);
}
Итак, мой вопрос... как, черт возьми, вы используете законные асинхронные методы ввода-вывода в архитектуре, основанной на синхронизации? Типичным ответом кажется «вы не можете» (как предложено в этом вызове асинхронных методов из синхронного контекста), но тогда я, должно быть, что-то упускаю, поскольку кажется совершенно разумным желание разгрузить работу, связанную с вводом-выводом, и позволить текущему поток выполняет другую работу в контекстах, не основанных на пользовательском интерфейсе.
Подробнее здесь:
https://stackoverflow.com/questions/230 ... r-boundary