您好我使用Filesystemwatcher& BackgroundWorker流程。
我有一个Windows窗体应用程序,它检查文件夹上的新文本文件,处理它们并从中创建xml文件。
我正在使用FSW监视文件夹上的新txt文件,该应用程序工作正常,但当文件夹收到大量文件(假设为1000)时,应用程序冻结,因为它正在处理所有这些文件。
我想添加一个后台工作者,所以FSW每次创建一个新文件时都会调用它,这样我们就可以在后台处理文件而不会冻结UI。
这个想法不起作用,因为对于每个创建的文件,我尝试调用RunWorkerAsync()方法,所以如果它忙于处理文件并且我尝试处理一个新文件,它将抛出以下错误:
“此BackgroundWorker当前正忙,无法同时运行多个任务。”
所以我尝试将方法循环一段时间直到它可用,但抛出了无限异常。 这是我的代码的简化版本:
private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
readFile();
}
private void readFile()
{
while (backgroundWorker1.IsBusy)
{
readFile();
}
backgroundWorker1.RunWorkerAsync(idx);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int i = (int)e.Argument;
i += 1;
e.Result = i;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = "Processing...";
this.Refresh();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
label1.Text = "Completed...";
this.Refresh();
idx = (int)e.Result;
}
抛出的异常说“在WindowsFormsApplication2.exe中发生了'System.StackOverflowException'类型的未处理异常,请确保没有无限循环或递归”
当然我可以删除FSW,但我想知道是否有办法让它们一起工作,有什么想法吗?
答案 0 :(得分:2)
您拥有的是经典的制作人/消费者问题。
使用System.Collections.Concurrent.ConcurrentQueue<string>
解决问题。
这是匆忙溢出堆栈的代码:
private void readFile()
{
while (backgroundWorker1.IsBusy)
{
readFile(); // the recursive call, will fail quickly
}
backgroundWorker1.RunWorkerAsync(idx);
}
这不仅会导致SO异常,还会阻止主线程 您需要一种更好的等待方式,ConcurrentQueue会为您提供。
答案 1 :(得分:1)
实例化新的BackgroundWorkers就像上面的Henk解决方案一样。
或者,您可以在不使用ThreadPool
。
private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
ThreadPool.QueueUserWorkItem(o => readFile(e));
}
public void readFile(System.IO.FileSystemEventArgs e)
{
this.BeginInvoke(new MethodInvoker(() =>
{
label1.Text = "Processing...";
this.Refresh(); //you shouldn't need this
}));
//your long running read/processing... doing something event args
this.BeginInvoke(new MethodInvoker(() =>
{
label1.Text = "Completed...";
this.Refresh();
idx = (int) e.Result;
}));
}
答案 2 :(得分:0)
为什么不在readFile中实例化一个新的BackgroundWorker而不是重用?