【问题标题】:StreamWriter Multi Threading C#StreamWriter 多线程 C#
【发布时间】:2013-10-18 17:04:34
【问题描述】:

我想就我的代码寻求帮助。我是一个新手,想在写入文本文件时实现安全的多线程。

    StreamWriter sw = new StreamWriter(@"C:\DailyLog.txt");
    private void Update(){
        var collection = Database.GetCollection<Entity>("products");
        StreamReader sr = new StreamReader(@"C:\LUSTK.txt");
            string[] line = sr.ReadLine().Split(new char[] { ';' });
            while (!sr.EndOfStream)
            {
                    line = sr.ReadLine().Split(new char[] { ';' });
                    t = delegate { 
                           UpdateEach(Convert.ToInt32(line[5])); 
                        }; 
                     new Thread(t).Start();
            }
            sr.Close();

    }
    private void UpdateEach(int stock)
    {
            sw.WriteLine(ean);

    }

我的代码没有错误,但似乎并未全部写入我的文本文件。我没有制作sw.Close(),因为我知道有些线程还没有完成。此外,我如何实现sw.Close 知道没有线程未完成。我的LUSTK.text 中有 500 万条记录将由StreamReader 读取,每个记录都创建一个线程,每个线程访问相同的文本文件。

【问题讨论】:

    标签: c# multithreading file streamreader streamwriter


    【解决方案1】:

    您将无法从不同的线程同时写入同一个写入器。该对象并非旨在支持并发访问。

    除此之外,从多个线程写入同一个文件的一般想法是有缺陷的。您仍然只有一个物理磁盘,而且它只能旋转得如此之快。告诉它更快地做事不会让它旋转得更快。

    除此之外,您并没有像您所说的那样关闭编写器,因此,缓冲区没有被刷新。

    您还有一个错误,即您的匿名方法正在关闭line,并且所有方法都关闭了同一个变量,该变量正在发生变化。重要的是他们每个人都关闭了自己不会改变的标识符。 (这可以简单地通过在while 循环中声明line inside 来完成。)但是由于您不应该一开始就使用多个线程,因此没有真正需要关注这一点。

    你也可以使用File.ReadLinesFile.WriteAllLines来做你的文件IO;它会产生更简洁的代码:

    var values = File.ReadLines(inputFile)
        .Select(line => line.Split(';')[5]);
    File.WriteAllLines(outputFile, values);
    

    如果您想要并行化这个过程,那是因为您在阅读该行之后和编写该行之前对每个项目执行了一些 CPU 密集型工作。如前所述,并行化实际的文件 IO 可能是有害的,没有帮助。在这种情况下,CPU 绑定的工作只是拆分行并获取一个值,与文件 IO 相比,这可能快得惊人。例如,如果您需要访问数据库或在每一行上进行一些昂贵的处理,那么您将考虑并行化只是这部分工作,同时通过单个线程同步文件 IO。

    【讨论】:

    • 谢谢,如果使用 StreamWriter,我可以使用数组列表来存储这些 ean 吗?在所有线程完成后,我将遍历数组列表并执行 StreamWriter。
    • @Wao 也许,如果您有足够的内存来保存这么多数据。你可能不会。我展示的代码仍在流式传输数据并一次处理一行;它不会将所有行都拉入内存。对于这么大的文件,这可能是一件很重要的事情。
    • @Wao 正如我所说,使用多线程确实没有什么好处。只是不要。
    【解决方案2】:

    StreamWriter 根本不是线程安全的;您需要通过lock 或类似方式同步对此的访问。但是,我建议您重新考虑您的策略:

    • 启动大量线程是一个真的坏主意 - 线程实际上非常昂贵,不应该用于小型工作(TaskThreadPool 可能很好,不过)- 少量线程可能会从线程安全队列中单独出队会更可取
    • 您无法保证输出的顺序
    • 坦率地说,我认为 IO 是您最大的性能问题,并且不受线程数量的影响(或更糟糕的是:可能受到不利影响)

    【讨论】:

    • 感谢您的信息。但是如果我使用队列,我需要一些时间来完成 500 万条记录,对吧?
    • @Wao 是的,通过读取这么多数据然后再次将其写出来处理一个 500 万行的文件需要一些时间。这是不可避免的,并行化也无济于事。唯一的办法就是购买具有更快读/写速度的磁盘驱动器,即固态驱动器。或者获取更少的数据。
    • 感谢先生的想法。
    • @Marc Gravell,你能看看这个问题吗? stackoverflow.com/questions/19270449/…
    猜你喜欢
    • 2017-01-15
    • 2011-04-05
    • 2011-04-05
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    相关资源
    最近更新 更多