Многопоточная обработка большого массива через ThreadPool с возможностью остановки - C#

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

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

Добрый день! Возникла такая задача. В массиве 200 тыс. строк. Их нужно обработать с помощью довольно быстрой функции с максимальной скоростью. Я использую ThreadPool для обработки:
   foreach (string line in lines)
            {
                ThreadPool.QueueUserWorkItem(arg =>
                {
                    CheckMulti((object)line);
                });
            }
Но мне нужно чтобы после выполнения операции появился MessageBox. То есть нужно подождать, пока не завершится обработка всех строк. И здесь такая проблема. Раньше в подобных ситуациях я использовал:
RunningWorkers = lines.count;
foreach (string line in lines)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(checkMulti), (object)file);
    Thread.Sleep(10);
}
 
//ожидание threadpool
lock (WorkerLocker)
{
    while (RunningWorkers > 0)
    {
        Monitor.Wait(WorkerLocker);
    }
}
 
public void CheckMulti(object line)
{
    //обработка строки
    ...
    //
 
    lock (WorkerLocker)
    {
        RunningWorkers--;
        Monitor.Pulse(WorkerLocker);
    }
}
Но получается, что на каждой строчке стоит ожидание Thread.Sleep(10), отчего обработка получается очень медленной. Возможно ли как-то по-другому переписать этот код, чтобы была максимальная скорость и возможность дождаться конца обработки? Варианты с Foreach.Parallel или Task просьба не предлагать, мне нужно именно на ThreadPool.

Решение задачи: «Многопоточная обработка большого массива через ThreadPool с возможностью остановки»

textual
Листинг программы
    public static class ParallelExtender
    {
        public delegate TResult Func<in T, out TResult>(T arg);
        public static TResult[] MapAsync<T, TResult>(this ICollection<T> collection, Func<T, TResult> func)
        {
            var result = new TResult[collection.Count];
            var allDone = new ManualResetEvent(false);
            int completed = 0;
            int i = 0;
            foreach (var item in collection)
            {
                T t = item;
                int index = i;
                ThreadPool.QueueUserWorkItem(_ =>
                {
                    result[index] = func(t);
                    if (Interlocked.Increment(ref completed) == result.Length)
                        allDone.Set();
                });
                i++;
            }
            allDone.WaitOne();
            return result;
        }
    }

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


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

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

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