如何在.NET

时间:2015-07-09 13:38:27

标签: c# .net multithreading

问题:读入数据堆积起来,等待写入。

我有一个基本的ETL过程,它读入文件,转换数据,然后将数据写入另一个文件。由于我在多核系统上,我正在尝试使用多个线程来执行此操作。我的问题是读者超过了作者:许多文件最终被读取并且他们的数据被转换,但是他们堆积起来等待写作。

我想要的是在读取的文件和写入的文件之间取得平衡,同时仍然使用多个线程。

我在.NET库(C#4.0)中尝试过各种各样的东西。我认为虽然有一些我不理解的东西,并且这比仅仅使用ThreadThreadPool.QueueUserWorkItemTask它们在基本示例中出现的方式要复杂得多。我找到了。

例如,假设我尝试这样的事情:

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

1 个答案:

答案 0 :(得分:2)

我正是这样做并将其分解为3


  • 只有一组头 - 这样做并不是一件好事 关闭文件并将文本传递给下一步
  • 过程

BlockingCollection与Upperbound(有界容量)一起使用
使用Upperbound时,快速步骤不会远远超过慢速

所以你有多个核心。你可能是IO绑定的。

您可以并行处理(步骤2)但除非您有一些复杂的变换,否则它不会产生任何影响。

尝试在不同的物理设备上进行读写。