#c#
#c#
Вопрос:
Я пытаюсь понять доступные параллельные подходы и пытаюсь узнать, какой из них более подходит для моего текущего сценария. Моя работа заключается в том, чтобы получить статус списка URL-адресов независимо от того, возвращают ли они HttpStatus OK
или Not OK
одновременно, ограничить количество потоков и убедиться, что предоставленные максимальные потоки выполняются ВСЕ время, независимо от пакетного выполнения потока. Для этого я попытался использовать параллельную библиотеку задач, и она отлично работает.
Код
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = 3
};
Parallel.ForEach(ListMonitorUrl, parallelOptions, i =>
{
LogMailError("URL: " i.URL " DateTime: " DateTime.Now " Thread ID: " Thread.CurrentThread.ManagedThreadId, LogFile);
VerifyWebAppUrl(i);
});
public MonitorURLs VerifyWebAppUrl(MonitorURLs Model)
{
List<string> UrlsWithNotOKResponse = new List<string>();
try
{
var request = (HttpWebRequest)WebRequest.Create(Model.URL);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK amp;amp; Model.Status == "A")
Model.ChangeOfStatus = true;
if (response.StatusCode == HttpStatusCode.OK amp;amp; Model.Status != "A")
Model.ChangeOfStatus = true;
}
}
catch (Exception ex)
{
Model.ChangeOfStatus = false;
}
return Model;
}
Я видел, что есть и другие подходы, такие как SemaphoreSlim
, Task
. Но я не уверен, что лучше всего подходит для моего сценария. Пожалуйста, предложите.
Комментарии:
1. «Пожалуйста, предложите» вопросы лучше работать на другой сайт
Ответ №1:
Parallel.ForEach
полностью не подходит для рабочих нагрузок, связанных с вводом-выводом, вы расходуете ценные ресурсы, ожидая портов завершения ввода-вывода, и регулируете работу планировщика задач по умолчанию / Threadpool (что не только без необходимости создаст узкое место, но и истощит другие части вашего приложения).
Правильным подходом будет что-то, что поддерживает шаблон Async Await, такой Task.WhenAll
как, реактивные расширения, поток данных TPL, и т.д.
Вот простой пример потока данных Microsoft TPL. Вы можете получить систему nuget здесь .Многопоточность.Задачи.Поток данных.
Преимущества заключаются в:
- Это работает из коробки с шаблоном Async Await
- Вы можете контролировать максимальные степени параллелизма, выбирайте столько, сколько может обработать ваша система / приложение (тогда это значение может быть намного больше
Parallel.ForEach
) - Он прост в использовании
- Вы можете создавать более сложные конвейеры обработки, когда будете готовы
- Вы не будете регулировать пул потоков и будете намного эффективнее и производительнее
Пример
public async List<Model> GetDeadUrls(List<Model> models)
{
var action = new ActionBlock<Model>(
// your async method
model => VerifyWebAppUrl(model),
//some options
new ExecutionDataflowBlockOptions()
{
// CancellationToken = sometoken,
// pick as many as your system can handle
MaxDegreeOfParallelism = 100,
// doesn't need to be ordered
EnsureOrdered = false,
// slight performance tweak, there is only one
SingleProducerConstrained = true
});
// start
foreach (var model in models)
action.Post(model);
// mark it as completed
action.Complete();
// wait for it to finish
await action.Completion;
// filter the results
return models.Where(x => x.ChangeOfStatus).ToList();
}
Асинхронный метод
public async Task<Model> VerifyWebAppUrl(Model model)
{
try
{
var request = (HttpWebRequest)WebRequest.Create(model.URL);
using (var response = (HttpWebResponse) await request.GetResponseAsync())
{
if (response.StatusCode != HttpStatusCode.OK amp;amp; model.Status == "A")
model.ChangeOfStatus = true;
if (response.StatusCode == HttpStatusCode.OK amp;amp; model.Status != "A")
model.ChangeOfStatus = true;
}
}
catch (Exception ex)
{
// this looks suspicious
model.ChangeOfStatus = false;
}
return model;
}
Примечание: Это абсолютно непроверенный и только пример
Комментарии:
1. Теперь я могу понять разницу между операциями ввода-вывода и привязкой к процессору. Как насчет использования Parallel. Foreach с асинхронной операцией?? Не решит ли это проблему потока, ожидающего завершения операции ввода-вывода, поскольку асинхронная обработка может выполняться без ожидания результатов??