Как узнать, все ли потоки пула потоков уже выполнили свои задачи? - PullRequest
7 голосов
/ 22 марта 2010

У меня есть это приложение, которое будет просматривать все папки в данном каталоге и искать PDF. Если файл PDF найден, приложение будет считать его страницы с помощью ITextSharp. Я сделал это с помощью потока, чтобы рекурсивно сканировать все папки на наличие PDF, а затем, если PDF найден, он будет поставлен в очередь в пуле потоков. Код выглядит так:

//spawn a thread to handle the processing of pdf on each folder.
                var th = new Thread(() =>
                {
                    pdfDirectories = Directory.GetDirectories(pdfPath);
                    processDir(pdfDirectories);
                });
                th.Start();



 private void processDir(string[] dirs)
        {
            foreach (var dir in dirs)
            {
                pdfFiles = Directory.GetFiles(dir, "*.pdf");
                processFiles(pdfFiles);

                string[] newdir = Directory.GetDirectories(dir);
                processDir(newdir);
            }
        }



private void processFiles(string[] files)
        {
            foreach (var pdf in files)
            {
                ThreadPoolHelper.QueueUserWorkItem(
                    new { path = pdf },
                    (data) => { processPDF(data.path); }
                    );
            }
        }

Моя проблема в том, как мне узнать, что поток пула потоков завершил обработку всех элементов в очереди, чтобы я мог сказать пользователю, что приложение выполнено с его намеченной задачей?

Ответы [ 2 ]

4 голосов
/ 22 марта 2010

Как правило, я бы сделал что-то подобное, имея переменную counter. Для каждого рабочего элемента, который вы ставите в очередь в ThreadPool, добавьте его в переменную counter. Затем при обработке вы уменьшите значение счетчика.

Убедитесь, что вы делаете приращение и убывание с помощью методов класса Interlocked, так как это гарантирует, что все будет выполнено потокобезопасным способом.

Как только счетчик достигнет нуля, вы можете указать, что задачи выполнены, используя ManualResetEvent

Если у вас есть доступ к .NET 4, вы можете использовать новый класс CountdownEvent, чтобы сделать то же самое.

2 голосов
/ 22 марта 2010

1) Как узнать, завершены ли все темы?

Вам нужно будет разрешить потокам выполнять свою собственную регистрацию / выписку, заключив код в скобки между:

Interlocked.Increment(ref jobCounter);
// your code
Interlocked.Decrement(ref jobCounter);

Если это слишком запутывает ваших анонимных делегатов, просто используйте методы-обертки. Возможно, вам также придется добавить обработку исключений.

Взаимосвязанный подход по-прежнему избавляет от проблемы ожидания, когда он станет равным 0, цикл с Sleep () является слабым, но в данном случае жизнеспособным решением.

2) Вы запускаете темы в рекурсивном обходчике деревьев. Будьте осторожны, вы, вероятно, создаете их слишком много, и это ухудшит производительность.

...