如何知道所有线程池的线程是否已完成其任务?

时间:2010-03-22 08:07:59

标签: c# .net multithreading threadpool

我有这个应用程序将递归给定目录中的所有文件夹并查找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 个答案:

答案 0 :(得分:4)

一般来说,我会通过计算器变量来做这样的事情。 对于您在ThreadPool中排队的每个工作项,将一个加到计数器变量中。 然后当它被处理时,你会减少计数器变量。

确保通过Interlocked类上的方法执行递增和递减,因为这将确保以线程安全的方式完成任务。

一旦计数器达到零,您可以使用ManualResetEvent

标记任务已完成

如果您可以访问.NET 4,那么您可以使用新的CountdownEvent类来执行类似的操作。

答案 1 :(得分:2)

1)如何知道所有线程是否都已完成?

您必须让线程自行办理入住/退房手续,方法是将代码括在:

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

如果这会让你的匿名代表太多,那么只需使用包装器方法。您可能还必须添加异常处理。

互锁方法仍然存在等待它变为0的问题,具有Sleep()的循环是弱的,但在这种情况下是可行的解决方案。

2)您正在递归Tree walker中启动线程。小心,你可能创造了太多的东西,这会损害性能。