如何知道所有线程池的线程是否已完成其任务?
我有这个应用程序将递归给定目录中的所有文件夹并查找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); } ); } }
我的问题是,我怎么知道线程池的线程已经完成处理所有排队的项目,所以我可以告诉用户应用程序已完成其预期的任务?
通常我会通过计数器变量做这样的事情。 对于在ThreadPool
排队的每个工作项,将一个添加到计数器变量。 然后当它被处理时,你会减少计数器变量。
确保通过Interlocked
类上的方法执行递增和递减,因为这将确保以线程安全的方式完成操作。
一旦计数器达到零,您就可以使用ManualResetEvent
标记任务已完成
如果您可以访问.NET 4,那么您可以使用新的CountdownEvent
类来执行类似的操作。
1)如何知道所有线程是否完成?
您必须让线程执行自己的签入/签出,将代码括在:
Interlocked.Increment(ref jobCounter); // your code Interlocked.Decrement(ref jobCounter);
如果这会让你的匿名代表太多,那么只需使用包装器方法。 您可能还必须添加exception处理。
互锁方法仍然存在等待它变为0的问题,具有Sleep()的循环是弱的,但在这种情况下是可行的解决方案。
2)您正在递归Tree walker中启动线程。 要小心,你可能创造了太多的东西,这将损害性能。
- 从.net core 2.0中的动态加载程序集调试代码
- 处理BigInteger问题
- 如何使Entity Framework生成的类实现INotifyPropertyChanged?
- 防止Resharper“可能的空引用exception”警告
- Unity3D – 我可以使用.NET 4.5程序集作为外部库吗?
- 如何更改安装项目中的窗口Applicatoin的默认图标
- 在IIS上尝试我的WCF数据服务时得到“401 – 未经授权”
- 警告:“…覆盖Object.Equals(对象o)但不覆盖Object.GetHashCode()”
- .net XmlSerialize抛出“无法在使用ConformanceLevel.Fragment创建的编写器上调用WriteStartDocument”