问题:读入数据堆积起来,等待写入。
我有一个基本的ETL过程,它读入文件,转换数据,然后将数据写入另一个文件。由于我在多核系统上,我正在尝试使用多个线程来执行此操作。我的问题是读者超过了作者:许多文件最终被读取并且他们的数据被转换,但是他们堆积起来等待写作。
我想要的是在读取的文件和写入的文件之间取得平衡,同时仍然使用多个线程。
我在.NET库(C#4.0)中尝试过各种各样的东西。我认为虽然有一些我不理解的东西,并且这比仅仅使用Thread
或ThreadPool.QueueUserWorkItem
或Task
它们在基本示例中出现的方式要复杂得多。我找到了。
例如,假设我尝试这样的事情:
Task task = new Task(() => PerformEtl(sourceFile));
task.start();
如果我记录正在读取的文件和正在写入的文件,它就像是10比1的比例。在长期运行的过程中,这是不可持续的。
必须有一些我无知或无法想到的基本多线程/多处理模式。有谁知道我应该从哪里去?感谢。
解决:
感谢@Blam。
下面是一些示例/伪代码,用于说明如何使用.NET库实现生产者 - 消费者模式,如@Blam所示。
// Adapted from: https://msdn.microsoft.com/en-us/library/dd997371(v=vs.100).aspx
BlockingCollection<object> dataItems = new BlockingCollection<object>(10);
List<Task> tasks = new List<Task>();
tasks.Add(
// Producer.
Task.Factory.StartNew(() =>
{
for (;;)
{
string filePath = GetNextFile();
if (filePath == null) break;
object data = ProcessData(ReadData(file));
dataItems.Add(data);
}
dataItems.CompleteAdding();
})
);
tasks.Add(
// Consumer.
Task.Factory.StartNew(() =>
{
while (!dataItems.IsCompleted))
{
object data;
try
{
data = dataItems.Take();
WriteData(data);
}
catch(InvalidOperationException ioe)
{
Console.Error.WriteLine(ioe.Message);
}
}
})
);
Task.WaitAll(tasks.ToArray());
MSDN讨论在这里:https://msdn.microsoft.com/en-us/library/dd997371(v=vs.100).aspx
答案 0 :(得分:2)
我正是这样做并将其分解为3
将BlockingCollection与Upperbound(有界容量)一起使用
使用Upperbound时,快速步骤不会远远超过慢速
所以你有多个核心。你可能是IO绑定的。
您可以并行处理(步骤2)但除非您有一些复杂的变换,否则它不会产生任何影响。
尝试在不同的物理设备上进行读写。