有一个应用程序在某些条件下对大型txt文件进行排序。 我需要以5个线程开始,但我从foreach循环的文件中逐行读取。 如果我用我的代码启动5个线程,所有线程将采用相同的行。
这是我的代码,我开始1个帖子:
Thread[] thr;
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button4.Enabled = true;
decimal value = 1;
int i = 0;
int j = (int)(value);
thr = new Thread[j];
for (; i < j; i++)
{
thr[i] = new Thread(new ThreadStart(go));
thr[i].IsBackground = true;
thr[i].Start();
}
}
private static IEnumerable<string> ReadLineFromFile(TextReader fileReader)
{
using (fileReader)
{
string currentLine;
while ((currentLine = fileReader.ReadLine()) != null)
{
yield return currentLine;
}
}
}
public void go()
{
while (true)
{
TextReader readFile = new StreamReader(file_path, System.Text.Encoding.UTF8, true);
foreach (string line in ReadLineFromFile(readFile))
{
if (line.Split(':')[0].Contains("@"))
{
string out_line = line.Split(':')[0].Replace("+", "") + ":" + line.Split(':')[1];
lock (locker)
{
mail_count++;
log_mail(mail_count);
mail.Add(out_line.Trim().Replace(";", ":"));
}
}
else
{
string out_line = line.Split(':')[0].Replace("+", "") + ":" + line.Split(':')[1];
lock (locker)
{
rubbish_count++;
log_rubbish(rubbish_count);
rubbish.Add(out_line.Trim());
}
}
}
MessageBox.Show("Ready");
BeginInvoke(
new MethodInvoker(() =>
{
button1.Enabled = true;
button4.Enabled = false;
}));
break;
}
}
答案 0 :(得分:4)
所有线程都无法读取同一个文件,并且从共享文件中读取是困难且低效的。
在您的主要功能中,您需要以下内容:
Parallel.ForEach(System.IO.File.ReadLines(file_path, System.Text.Encoding.UTF8),
line => ProcessOneLine(line)
);
然后ProcessOneLine将执行.Split(':')
等。
答案 1 :(得分:3)
为什么不采用通常的生产者 - 消费者模式?创建一个线程读取文件,将行放在某个共享集合中,其他线程只从集合中选择数据并进行处理。
更多 - 您可以从文件中读取并为每行创建Task
,它将负责处理此行并将结果放入输出集合中。
这似乎比5个线程试图读取同一个文件而不是多次读取同一行更好。
答案 2 :(得分:0)
我想确认并扩展Pako所说的内容。其他线程应该使用包含数据的共享集合中的数据并对其进行处理。
让多个线程访问文本文件听起来像是可能发生竞争条件。如果线程正在更改文件而另一个线程正在从中读取文件,则可能会发生基本上不可预测的结果。
过去使用多个线程访问同一个文本文件并且可以推荐它时,我也经历过BSOD。但是,如果您坚持这样做,我建议您查看“lock”关键字和单例设计模式。这将允许您确保一次只有一个线程正在访问该文件。
相关链接:
http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.80).aspx http://en.wikipedia.org/wiki/Singleton_pattern