Мы работаем над старым компаратором.
Когда пользователь проводит исследование, мы одновременно вызываем 10-30 различных веб-сервисов (REST, SOAP). Довольно классически так. Каждый веб-сервис представлен Клиентом в нашем приложении.
Так код выглядит так:
//Get the request list of client to call
clientRqListToCall = BuildRequest(userContext);
List<Task> taskList = new List<Task>();
//Call the different client
Foreach (ClientRequest clientRq in clientRqListToCall) {
Task task = Task.Run(() => CallClient(clientRq));
taskList.Add(task);
}
//wait client until timeOut
Task mainWaiterTask = Task.WhenAll(taskList);
mainTask.ConfigureAwait(false);
mainTask.Wait(timeout);
Simple. (Не уверен, что требуется configureAwait). Ответ каждого клиента хранится в поле ClientRequest, поэтому мы не используем mainTask.Result (если время ожидания клиента, нам нужно иметь возможность продолжить работу с чужими, и они очень много времени ожидания! Поведение вызова клиента довольно похоже на огонь и забыл).
Приложение немного старое, наша поисковая система работает синхронно. Вызов различных веб-сервисов находится в другом CallClient callTree, в соответствии с контекстом исследования, перед вызовом веб-сервиса вызывается от 5 до 15 различных функций. Каждый веб-сервис довольно длинный (от 1 до 15 секунд)! Этот момент кажется важным! Это не пингует простые запросы пингов.
Действия / Изменения?
Так что это проблема ввода-вывода, мы знаем, что Task.Run работает довольно хорошо для решения проблемы, связанной с процессором, а не для ввода-вывода, вопрос в том, как сделать этот код лучше?
Мы прочитали много разных статей на эту тему, благодаря Стивену Клири (http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html)
Но мы не уверены в нашем выборе / дорожной карте, поэтому я выкладываю этот билет.
Мы могли бы сделать код асинхронным, но нам пришлось бы переработать все дерево вызовов CallClient (сотни функций). Это единственное решение? Конечно, мы можем мигрировать веб-сервис один за другим, используя взломанный аргумент bool (https://msdn.microsoft.com/en-us/magazine/mt238404.aspx).
=> Должны ли мы начать с самого дорогого (с точки зрения IO) веб-сервиса, или важно только количество вызовов веб-сервиса, и поэтому нам следует начать с самого простого?
Другими словами, если у меня есть 1 большой клиент со средним значением ответа 10 с и большим количеством данных, мы должны сначала начать асинхронизацию? Или следует начинать с маленьких (1-2 с) с одинаковым количеством данных. Я могу ошибаться, но поток блокируется синхронно до тех пор, пока task.run () не завершит работу, так что задача 10s блокирует поток на все время, но с точки зрения освобождения ввода-вывода поток может быть лучше. Важен ли объем загрузки данных? или мы должны только прощаться с точки зрения таймера веб-службы?
Task.Run использует приложение threadPool, нам нужно выбирать между .Run (...) или Task.Factory.StartNew (..., TaskCreationOptions.LongRunning), чтобы (в большинстве случаев) ,
создать новую тему и, возможно, стало лучше.
=> Я провел некоторый тест на subjet, используя консольное приложение. Кажется, что .Run () работает на 25-33% быстрее, чем Task.Factory.StartNew во всех сценариях.
Конечно, это ожидаемый результат, но в веб-приложении с примерно 200 пользователями,
Я не уверен, что результат будет таким же, я боюсь, что пул будет заполнен, и Задача перейдет друг к другу без конца.
Примечание. Если используется startNew, WaitAll (тайм-аут) заменяет WhenAll.
Сегодня у нас в среднем от 20 до 50 клиентов могут проводить исследования одновременно. Приложение работает без больших проблем, у нас нет тупиков, но иногда мы видим некоторую задержку в выполнении задачи на нашей стороне. Наше использование процессора довольно низкое (<10%), Ram тоже зеленый (<25%) </p>
Я знаю, что есть много билетов на Задачи, но сложно объединить их, чтобы соответствовать нашей задаче. И мы также читаем противоречивые советы.