Parallel.ForEach выполнить множество операций в отдельных потоках - C#

Узнай цену своей работы

Формулировка задачи:

Народ, кто-нибудь может объяснить в каких ситуациях нужно использовать перегрузку Parallel.ForEach, в которой есть localInit, body, localFinally. Я хочу парсить сайт и в localFinally помещать результат парсинга в блокирующую очередь, но нельзя этого сделать, так как я передаю в метод в качестве первого параметра string (IEnumerable<TSource> source), то и в остальных методах идёт инициализация и финальные действия тоже с string. Короче что-то я вообще не въеду, где это может пригодится. А то что я хочу делать походу проще оставить как есть сейчас, всё делается в body. Я себе это представлял как с BackgroundWorker, типа как события в нём body это как DoWork, localFinally это как RunWorkerCompleted. Эта перегрузка, о которой я говорю.
public static ParallelLoopResult ForEach<TSource, TLocal>(
IEnumerable<TSource> source,
ParallelOptions parallelOptions, 
Func<TLocal> localInit, 
Func<TSource, ParallelLoopState, TLocal, TLocal> body, 
Action<TLocal> localFinally);
        public void ParseAsync(string[] webSites)
        {
            int parsedDocs = 0;
 
            ConcurrentQueue<string> errors = new ConcurrentQueue<string>();
            ConcurrentQueue<T> infos = new ConcurrentQueue<T>();
 
            ParallelOptions parOpt = new ParallelOptions();
            _cancellationTokenSource = new CancellationTokenSource();
            parOpt.CancellationToken = _cancellationTokenSource.Token;
 
            Func<string> localInit = () =>
                {
                    return "";
                };
            Func<string, ParallelLoopState, string, string> body = (site, pLoopState, something) =>
            {
                T info;
                if (parOpt.CancellationToken.IsCancellationRequested)
                    parOpt.CancellationToken.ThrowIfCancellationRequested();
 
                try
                {
                    if (_webSiteParser.Parse(site, out info))
                    {
                        infos.Enqueue(info);
                        OnWebSiteParsed(info, ++parsedDocs, errors.Count);
                    }
                    else
                    {
                        OnParsingWasFailured(site, null);
                        errors.Enqueue(site);
                    }
                }
                catch (Exception exc)
                {
                    OnParsingWasFailured(site, exc);
                    errors.Enqueue(site);
                }
                return string.Empty;
            };
            Action<string> localFinally = (site) =>
            {
 
            };
 
            Parallel.ForEach(webSites, parOpt, localInit, body, localFinally);
        }

Решение задачи: «Parallel.ForEach выполнить множество операций в отдельных потоках»

textual
Листинг программы
static double sum = 0.0;  // Окончательный результат
static object sync = new object(); // Объект для синхронизации
 
static void Main()
{
   // Параллельный расчет суммы корней всех чисел от 1 до 10,000,000
   Parallel.ForEach(Enumerable.Range(1, 10000000), Init, Body, Finally);
   Console.WriteLine(sum);
}
 
// Генерирует изначальное значение для локального промежутка
static double Init()
{
   return 0.0;
}
 
// Используется в расчете локальной суммы определенной части коллекции
static double Body(int x, ParallelLoopState state, double local)
{
   return local + Math.Sqrt(x);
}
 
// Здесь происходит обращение к общему ресурсу с использованием синхронизации - расчитывается сумма локальных сумм.
static void Finally(double local)
{
   lock (sync) sum += local;
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 4.2 из 5
Похожие ответы