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;
}