2016-07-24 4 views
8

Я использую asp.net Web API 2 и Entity Framework 6.асинхронной ждут вызова долго выполняющиеся синхронной и асинхронной методы

Оригинальный псевдокод

public IHttpActionResult GetProductLabel(int productId) 
{ 
     var productDetails = repository.GetProductDetails(productId); 
     var label = labelCalculator.Render(productDetails); 
     return Ok(label); 
} 

Модифицированный код

public async Task<IHttpActionResult> GetProductLabel(int productId) 
{ 
     var productDetails = await repository.GetProductDetailsAsync(productId); // 1 long second as this call goes into sub services 
     var label = labelCalculator.Render(productDetails); // 1.5 seconds synchrounous code 
     return Ok(label); 
} 

Перед моим изменением все шло синхронно.

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

Затем я делаю вызов синхронизации в библиотеку рендеринга, которая предлагает только методы синхронизации. Расчет занимает 1,5 секунды.

Есть ли еще какая-то польза от удаленной службы database_service, вызывающей вызов async-await, но второй вызов нет? И есть ли что-нибудь, что я мог бы еще улучшить?

Примечание

Причина, почему я спрашиваю это потому, что:

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

Итак, когда первый удаленный вызов database_service обрабатывается и ожидает этого 1 секунду, поток возвращается в IIS ?? !!

Но как насчет расчета 2-й метки, составляющей 1,5 секунды, которая снова заблокирует текущую нить в течение 1,5 секунд?

Итак, я освобождаю и блокирую поток, что не имеет смысла или что вы думаете?

+0

Вы не используете 'Task.FromResult', если у вас есть' async', просто выполните 'return label;' вы имели в виду не использовать async/wait в первом примере? –

+0

Я знаю ... поэтому я представил вам «модифицированный код», который вы предлагаете сейчас. – Pascal

ответ

2

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

+0

Пожалуйста, также обращайтесь к моему первому вопросу: «Есть ли еще преимущество в том, что удаленная служба database_service вызывала вызов async-await, но второй вызов не был?» Спасибо :-) – Pascal

+0

Вы вызываете удаленный метод async, ожидающий пути в обоих примерах. Я довел это до вас в комментарии. Ваш первый код даже не будет компилироваться, поэтому я не могу сказать, как он будет сравнивать, потому что первый код не может работать. –

+0

Поэтому я написал «код псевдонима», поэтому он не может скомпилировать. ДА Я не имел в виду ожидания в своем первом образце. Это была опечатка для копирования/вставки. Я исправил это сейчас. – Pascal

1

Асинхронный код создает определенное продолжение под капотом, это своего рода синтетический сахар, чтобы сделать асинхронное программирование более синхронным.

В целом, в зависимости от самих операций, это может помочь асинхронно выполнять обе длительные задачи. Он будет использовать разные задачи под капотом для каждой отдельной задачи с большим сроком выполнения и запускать их асинхронно.

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

Если возможно, я бы сделал второй метод async, так как я не знаком с какими-либо серьезными недостатками использования задач и асинхронным ожиданием.

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

1

Есть еще польза, которую я сделал database_service удаленный вызов Асинхронный-ждет путь, но второй вызов не?

Да, этот вызов теперь не блокируется и может работать вместе с другим кодом, хотя он всего лишь на 1 секунду.

И есть ли что-нибудь, что я мог бы улучшить?

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

+0

Будет ли теперь неблокирующий вызов возвращать поток вызывающему абоненту за 1 секунду, чтобы IIS мог поместить другой HTTP-запрос в этот поток? Или поток возвращается только вызывающему абоненту, когда вызов метода асинхронный-ждут до конца? – Pascal

+0

Он вернет нить за 1 секунду. Подумайте об этом так: * все * неасинхронные операторы блокируют текущий поток --- даже что-то вроде 'var s =" Hello, World. "' --- это просто так быстро, что это не имеет значения. Многие методы async имеют такие утверждения, но это не мешает им использовать преимущества async. Ваш второй блокирующий вызов ведет себя одинаково - он не останавливает другие асинхронные вызовы, работающие асинхронно, это занимает много времени. –

Смежные вопросы