多个线程写入队列,一个线程在c#中从队列写入文件

时间:2017-04-19 17:49:50

标签: c# multithreading file-io thread-safety

在控制台应用程序中,我通过 Parallel.ForEach 循环(总大小~150 GB)从同一文件夹中读取数十万个文件(每个约30 MB)。循环的每个任务都会生成一个我需要写入磁盘的对象。为了避免生成数千个输出文件,我正在寻找一种将所有结果写入同一文件的方法。

锁定线程不是一个选项,因为我需要极高的性能并且将所有内容保存在内存中是不可行的。

我不熟悉多任务处理,除了 Parallel ... 循环,我在这个主题上找不到任何相关的SO线程。

如何创建排队系统(输出顺序并不重要) Parallel.ForEach 循环的线程将其输出写入,并且后台线程获取队列的对象并将其附加到磁盘上的一个大文件。

这是我到目前为止的内容

module Base = struct
  type t = Name of string
end

module Child = struct
  include Base
end

Child.Name "test" 
(* - : Child.t = Child.Name "test" *)

一个MyWriter对象将被实例化,应用程序的Main和它的WriteToFile方法在其他线程之后调用。然后可以在主线程中启动ParseData方法,并在NothingMoreToAdd设置为true时结束WriteToFile方法。

如果您对如何管理此排队和写入磁盘有任何建议。

1 个答案:

答案 0 :(得分:0)

这是快速而又脏的东西。当然,您可以根据自己的需要进行更改。 但基本上,它完成了你所要求的:并行读取多个文件并对它们做一些事情并将结果添加到队列并将结果保存到文件

  private static void Main(string[] args)
        {
            string outputFile = @"E:\output\file.txt";
            ConcurrentQueue<object> queue = new ConcurrentQueue<object>();

            string[] files = Directory.GetFiles(@"E:\100D3100\", "*.*", SearchOption.TopDirectoryOnly);
            bool isCompleted = false;

            Task t1 = new Task(() =>
            {
                Parallel.ForEach(files, file =>
                    {
                        queue.Enqueue(file);
                    });
                isCompleted = true;
            });

            t1.Start();

            Task t2 = new Task(() =>
               {
                   object file = new object();

                   while (isCompleted != true)
                   {
                       queue.TryDequeue(out file);
                       if (file != null)
                       {
                           string[] text = File.ReadAllLines(file.ToString());
                           File.AppendAllLines(outputFile, text);
                       }
                   }

                   foreach (var item in queue)
                   {
                       string[] text = File.ReadAllLines(file.ToString());
                       File.AppendAllLines(outputFile, text);
                   }
               });

            t2.Start();

            Task.WhenAll(t1, t2).Wait();
        }

旁注: 并行I / O非常依赖于硬件,尤其是在磁盘上完成时。