我想请求帮助我的代码。我是一个新手,想要在写入文本文件时实现安全的多线程。
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
中有5个记录要由StreamReader
读取,每个记录创建一个线程,每个线程访问相同的文本文件。
答案 0 :(得分:6)
您无法同时从不同的线程写入同一个编写器。该对象不是为支持并发访问而设计的。
除此之外,从多个线程写入同一文件的一般想法是有缺陷的。你仍然只有一个物理磁盘,它只能旋转得那么快。告诉它更快地做事情不会让它更快地旋转。
除此之外,正如你所说,你没有关闭编写器,因此缓冲区没有被刷新。
您还有一个错误,即您的匿名方法正在关闭line
,并且所有方法都在关闭同一个变量,该变量正在发生变化。重要的是,每个人都要关闭自己不会改变的标识符。 (这可以通过在line
循环中声明{/ 1}} 来完成。但是因为你不应该使用多个线程开始,所以没有必要专注于此。
您还可以使用while
和File.ReadLines
来执行文件IO;它产生了更清晰的代码:
File.WriteAllLines
如果您想要并行化此过程,那将是因为您在读取行之后和写入行之前对每个项目执行了一些CPU绑定工作。如前所述,并行化实际文件IO可能是有害的,没有帮助。在这种情况下,CPU绑定工作只是拆分线并获取一个值,与文件IO相比,这可能会非常快。例如,如果您需要访问数据库或在每一行上执行一些昂贵的处理,那么您可以考虑并行化工作的那部分,同时通过单个线程同步文件IO。 / p>
答案 1 :(得分:5)
StreamWriter
根本不是线程安全的;您需要通过lock
或类似方式同步对此的访问权限。但是,我建议一般重新考虑你的策略:
Task
或ThreadPool
虽然可能没问题 - 可能会从线程安全队列中单独出列的线程数量较少