C# 如何平衡.NET中的读写线程
问题:读取的数据堆积起来,等待写入 我有一个基本的ETL过程,读取文件,转换数据,然后将数据写入另一个文件。因为我在一个多核系统上,所以我尝试使用多个线程来执行这个操作。我的问题是,读者的速度超过了作者:许多文件最终被读取,数据被转换,但它们堆积起来等待写入 我想要的是在读取文件和写入文件之间保持平衡,同时仍然使用多线程 我在.NET库(C#4.0)中尝试了各种方法。我认为有一些东西我不明白,这肯定比简单地使用C# 如何平衡.NET中的读写线程,c#,.net,multithreading,C#,.net,Multithreading,问题:读取的数据堆积起来,等待写入 我有一个基本的ETL过程,读取文件,转换数据,然后将数据写入另一个文件。因为我在一个多核系统上,所以我尝试使用多个线程来执行这个操作。我的问题是,读者的速度超过了作者:许多文件最终被读取,数据被转换,但它们堆积起来等待写入 我想要的是在读取文件和写入文件之间保持平衡,同时仍然使用多线程 我在.NET库(C#4.0)中尝试了各种方法。我认为有一些东西我不明白,这肯定比简单地使用Thread或ThreadPool.QueueUserWorkItem或Task要复杂
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());
//改编自:https://msdn.microsoft.com/en-us/library/dd997371(v=vs.100).aspx
BlockingCollection数据项=新BlockingCollection(10);
列表任务=新列表();
任务。添加(
//制片人。
Task.Factory.StartNew(()=>
{
对于(;;)
{
字符串filePath=GetNextFile();
如果(filePath==null)中断;
对象数据=ProcessData(ReadData(file));
添加(数据);
}
dataItems.CompleteAdding();
})
);
任务。添加(
//消费者。
Task.Factory.StartNew(()=>
{
而(!dataItems.IsCompleted))
{
对象数据;
尝试
{
data=dataItems.Take();
写入数据(数据);
}
捕获(无效操作异常ioe)
{
Console.Error.WriteLine(ioe.Message);
}
}
})
);
Task.WaitAll(tasks.ToArray());
MSDN的讨论在这里:我就是这样做的,我把它分成3部分
- 阅读
只有一组头部-并行执行此操作没有任何好处
关闭文件并将文本传递到下一步 - 过程
- 写
上界时,快步不会比慢步走得太远 所以你有多个核心。你可能是被我束缚住了 您可以并行处理(步骤2),但除非您有一些复杂的转换,否则不会产生任何影响
尝试在不同的物理设备上读写。必须限制写入程序。这可以像信号量一样简单,在writer中调用WaitOne(),在readers中调用Release()。为什么不运行N个线程,每个线程都执行
,而(1){Read();Transform();Write();}
。无需节流。“节流写入程序”?我不应该限制读者的阅读吗?我想让读者放慢速度。@usr是的,我本质上想分配一定数量的线程,并将线程上运行的任务排队。但是,这在.NET中是如何工作的呢?(我是.NET的新手。)你能给我指出正确的方向吗?我认为框架应该决定线程的最佳数量。我认为消费者和制作人的意见是相反的。这听起来很有希望。我本应该想到“生产者-消费者”这个词,但我没有想到。我会研究你的建议。这很有效!谢谢我已经编辑了我的答案,为解决方案添加了一些伪代码。