3

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

    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知道没有线程未完成,我该如何实现。我有 500 万条记录LUSTK.text可供读取StreamReader,每个记录都创建一个线程,每个线程访问相同的文本文件。

4

2 回答 2

6

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

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

除此之外,正如您所说,您没有关闭编写器,因此,缓冲区没有被刷新。

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

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

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

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

于 2013-10-10T19:14:20.360 回答
5

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

  • 启动大量线程是一个非常糟糕的主意 - 线程实际上非常昂贵,并且不应该用于小项目的工作(不过,aTaskThreadPool可能很好) - 少量线程可能会从线程安全中单独出队队列会更好
  • 就输出而言,您将无法保证顺序
  • 坦率地说,我希望 IO 是您最大的性能问题,并且不受线程数量的影响(或更糟:可能会受到不利影响)
于 2013-10-10T19:15:56.857 回答