我有一个非常大的二进制数据文件(20+ GB),我需要解析,处理数据,然后写我的输出。我在处理如此大量的数据方面经验很少,虽然我在构思如何处理它时遇到了一些麻烦,但我确实有一个想法。注意:输入数据包含从IBM大型机检索到的大量记录,因此格式如下:
每条记录(行/行)的前4个字节是RDW(记录描述符字)。 RDW包含记录的长度(包括RDW)。由于RDW,即使文件是一个恒定的字节流,我也知道每个记录的结束位置。我可以将这个二进制文件转换为一个文本文件,将每两个字节转换为十六进制表示,并在记录末尾包含一个新的行字符,但我担心如果一个20多GB的二进制文件有多大,如果这样翻译。
因为我想将文件保留为二进制文件,所以我知道如何继续:
不幸的是,我设想了一个问题。读取“主”线程的工作速度比它产生的线程快得多,我担心会创建太多的线程。为了防止这种情况,我设想了这个解决方案(伪代码):
record = file.ReadRecord()
if(numberOfRunningWorkerThreads < MAX_THREADS)
SpawnWorkerThread(record);
else
WaitUntil(numberOfRunningWorkerThreads < MAX_THREADS)
但是,我不知道如何实现这样的功能,尤其是最后else
条件。我是多线程和异步的新手,我甚至不确定这两个术语之间的区别是什么。
有人能指出我正确的方向吗?
答案 0 :(得分:2)
我相信你正在寻找一个信号量(或者也许SemaphoreSlim可能也适合你)。信号量“限制可以同时访问资源或资源池的线程数”。信号量创建时具有特定数量的插槽。然后,您可以调用“WaitOne”等待可用插槽,并在完成插槽时调用“Release”。如果没有可用的插槽,“WaitOne”可以永远等待,或者直到发生超时。
因此,在您的情况下,主线程将调用WaitOne以等待可用的插槽。然后,在工作线程结束时,您可以调用Release来释放一个插槽。
.NET信号量: https://msdn.microsoft.com/en-us/library/system.threading.semaphore(v=vs.110).aspx
.NET SemaphoreSlim(轻量级信号量): https://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim(v=vs.110).aspx
答案 1 :(得分:2)
<强>解决方法1:强>
使用ThreadPool。设置MaxThreads,其中
设置可以同时处于活动状态的线程池的请求数。高于该数字的所有请求将保持排队,直到线程池线程可用。
类似的东西:
System.Threading.ThreadPool.SetMaxThreads(50, 1000);
// inside loop
ThreadPool.QueueUserWorkItem(ProcessRequest);
// end loop
ProcessRequest
是您开展工作的方法。
<强>溶液2:强>
如果您知道记录数量:请使用Parallel.For
并相应地设置MaxDegreeOfParallelism
。
Parallel.For(0, 1000, new ParallelOptions { MaxDegreeOfParallelism = 10 },
i => {
ProcessRequest(i);
});