C# 如何暂停创建新线程,直到旧线程结束 背景
我有一个非常大的二进制数据文件(20+GB),需要解析、处理数据,然后编写输出。我很少有处理如此大量数据的经验,虽然我在概念化如何处理数据方面有点困难,但我确实有一个想法。注意:输入数据包含许多从IBM大型机检索到的记录,因此其格式如下: 每条记录(行/行)的前4个字节是RDW(记录描述符字)。RDW包含记录的长度(包括RDW)。由于RDWs,即使文件是一个恒定的字节流,我也知道每个记录的结束位置。我可以将这个二进制文件转换为文本文件,将每两个字节转换为其十六进制表示形式,并在记录的末尾包含一个新行字符,但如果这样翻译,恐怕一个20+GB的二进制文件会有多大 因为我想将该文件保留为二进制文件,所以我有一个方法:C# 如何暂停创建新线程,直到旧线程结束 背景,c#,multithreading,file,asynchronous,C#,Multithreading,File,Asynchronous,我有一个非常大的二进制数据文件(20+GB),需要解析、处理数据,然后编写输出。我很少有处理如此大量数据的经验,虽然我在概念化如何处理数据方面有点困难,但我确实有一个想法。注意:输入数据包含许多从IBM大型机检索到的记录,因此其格式如下: 每条记录(行/行)的前4个字节是RDW(记录描述符字)。RDW包含记录的长度(包括RDW)。由于RDWs,即使文件是一个恒定的字节流,我也知道每个记录的结束位置。我可以将这个二进制文件转换为文本文件,将每两个字节转换为其十六进制表示形式,并在记录的末尾包含一个
- 工作线程解析数据,处理数据,并将其输出到某处。(我想我将把数据存储在SQLite数据库中。)
record=file.ReadRecord()
if(运行线程数<最大线程数)
SpawnWorkerThread(记录);
其他的
Waitill(运行线程数<最大线程数)
但是,我不知道如何实现这样的功能,尤其是最后的else
条件。我不熟悉多线程和异步,我甚至不知道这两个术语之间的区别是什么
有人能给我指出正确的方向吗?我相信您正在寻找信号灯(或者信号灯LIM可能也适用于您)。信号量“限制可以同时访问资源或资源池的线程数”。该信号量是使用特定数量的插槽创建的。然后,您可以调用“WaitOne”来等待可用的插槽,并在使用完插槽后调用“Release”。如果没有可用的插槽,“WaitOne”可以永远等待,或者直到超时发生 因此,在您的情况下,主线程将调用WaitOne来等待可用的插槽。然后,在辅助线程的末尾,您可以调用Release来释放一个插槽 .NET信号量: .NET信号量LIM(轻型信号量):
解决方案1: 使用。设置,哪个 设置可同时处于活动状态的对线程池的请求数。在线程池线程可用之前,所有超过该数目的请求都将保持排队状态 比如:
System.Threading.ThreadPool.SetMaxThreads(50, 1000);
// inside loop
ThreadPool.QueueUserWorkItem(ProcessRequest);
// end loop
其中,ProcessRequest
是执行此工作的方法
解决方案2:
如果您知道记录数:使用Parallel.For
并相应地设置maxdegreeofpparallelism
Parallel.For(0, 1000, new ParallelOptions { MaxDegreeOfParallelism = 10 },
i => {
ProcessRequest(i);
});
这听起来正是我要找的!非常感谢你!在我阅读了更多关于信号量和信号量lim的内容之前,我将暂缓将此标记为答案。@jdcac,这正是您所要求的,但它不是解决您问题的最佳方案。创建和销毁线程是有成本的,如果您为文件中的每个记录创建和销毁一个线程,那么该成本可能会超过您想要支付的成本。如果您希望同时运行的线程不超过N个,那么您的程序应该先创建N个线程,然后重新使用它们。这就是线程池为您所做的(请参见User270576的回答)。我不太熟悉线程池的工作原理,但据我所知,它并不适用于长时间运行的任务—这里可能是这样,也可能不是这样。我的第二个想法是,如果主线程比工作线程快得多,那么一次可以排队多少线程。我不确定队列或它所能容纳的资源是否有任何限制。为什么不让您的“主”线程将数据放入队列中呢。具有一组工作线程,每个工作线程从队列中提取。您必须确保队列是同步的,这样两个工作线程就不会将相同的数据出列。Parallel.ForEach也可能是一个不需要知道记录数的选项,只要它们可以创建一个枚举器逐个记录读取记录。@wiz true!
Parallel.For(0, 1000, new ParallelOptions { MaxDegreeOfParallelism = 10 },
i => {
ProcessRequest(i);
});