C# 后台工作人员';的进度条不工作
在执行某些任务时,BackgroundWorker的progressbar不会更新。我想了解的是,在遍历DirectoryInfo中的每个文件时,progressbar会移动。假设我们有20个“.sql”文件,而第一个完成的文件应该是5%、10%等等。 这是我的密码C# 后台工作人员';的进度条不工作,c#,backgroundworker,C#,Backgroundworker,在执行某些任务时,BackgroundWorker的progressbar不会更新。我想了解的是,在遍历DirectoryInfo中的每个文件时,progressbar会移动。假设我们有20个“.sql”文件,而第一个完成的文件应该是5%、10%等等。 这是我的密码 private void CSV_Click(object sender, RoutedEventArgs e) { try {
private void CSV_Click(object sender, RoutedEventArgs e)
{
try
{
btnExtract.IsEnabled = false;
workerextract.RunWorkerAsync();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
try
{
this.Dispatcher.Invoke(() =>
{
DirectoryInfo di = new DirectoryInfo(txtQueryfolder.Text);
files = di.GetFiles("*.sql").Count();
currentfile = 0;
foreach (FileInfo fi in di.GetFiles("*.sql"))
{
// Open the text file using a stream reader.
using (StreamReader sr = new StreamReader(fi.FullName))
{
// Read the stream to a string, and write the string to the console.
string line = sr.ReadToEnd();
//System.Windows.MessageBox.Show(line);
ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
currentfile++;
}
int percentage = (currentfile + 1) * 100 / files;
workerextract.ReportProgress(percentage);
}
});
}
catch(Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
private void workerextract_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBarExtract.Value = e.ProgressPercentage;
}
private void workerextract_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnExtract.IsEnabled = true;
System.Windows.MessageBox.Show("CSV Data extraction finished!");
}
我发现
私有void workerextract_ProgressChanged(对象发送方,
System.ComponentModel.ProgressChangedEventArgs(e)
100%时,在结束时调用一次。
而且
私有无效工作提取\运行工作完成(对象发送方,
RunWorkerCompletedEventArgs(e)
从未调用,因为我在末尾没有看到消息框
因此,我认为我在这里做错了什么,您能告诉我正确的方法吗?使用
this.Dispatcher.Invoke
在BackgroundWorker
的DoWork
事件中执行UI线程中的整个操作;这就是BackgroundWorker
天生要避免做的事情
此外,由于正在访问一个UI对象,即txtQueryfolder
,因此从dispatcher中展开代码时会出现错误
只需使用:
private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
string queryFolder = e.Argument.ToString();
try
{
DirectoryInfo di = new DirectoryInfo(queryFolder);
files = di.GetFiles("*.sql").Count();
currentfile = 0;
foreach (FileInfo fi in di.GetFiles("*.sql"))
{
// Open the text file using a stream reader.
using (StreamReader sr = new StreamReader(fi.FullName))
{
// Read the stream to a string, and write the string to the console.
string line = sr.ReadToEnd();
//System.Windows.MessageBox.Show(line);
// ExtractToCSV shouldn't access to a UI object.
ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
currentfile++;
}
int percentage = (currentfile + 1) * 100 / files;
workerextract.ReportProgress(percentage);
}
}
catch (Exception ex)
{
// Don't use MessageBox in a thread different from the UI one. Just set the result (e.Result) and get that in the RunWorkerCompleted event.
// System.Windows.MessageBox.Show(ex.Message);
}
}
调用RunWorkerAsync
方法时,只需添加如下参数:
workerextrac.RunWorkerAsync(txtQueryfolder.Text);
问题是在Dispatcher.Invoke中包装整个DoWork。 我只需要包装那些与UI交互的代码。 因此,我适当地修改了代码,它可以正常工作
private void workerextract_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
try
{
this.Dispatcher.Invoke(() =>
{
di = new DirectoryInfo(txtQueryfolder.Text);
});
files = di.GetFiles("*.sql").Count();
currentfile = 0;
foreach (FileInfo fi in di.GetFiles("*.sql"))
{
// Open the text file using a stream reader.
using (StreamReader sr = new StreamReader(fi.FullName))
{
// Read the stream to a string, and write the string to the console.
string line = sr.ReadToEnd();
this.Dispatcher.Invoke(() =>
{
//System.Windows.MessageBox.Show(line);
ExtractToCSV(line, System.IO.Path.GetFileNameWithoutExtension(fi.Name));
});
currentfile++;
}
int percentage = (currentfile + 1) * 100 / files;
workerextract.ReportProgress(percentage);
}
}
catch(Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
感谢大家为我们指明了方向。为什么它会被多次调用?您只报告一次进度-在最后。你根本没有在循环中报告进度。我修改了我的代码,即使是在循环中,它也只调用一次。你需要创建一个后台工作程序,然后让
调度程序将大部分代码移回UI线程。为什么要这样做?所以停止从后台工作代码访问UI对象。或者,如果您“必须”访问UI对象,只需使用Dispatcher.Invoke
,而不是整个循环来包装这些行。为什么要生成一个后台工作程序来在UI线程上运行它this.Dispatcher.Invoke
。这违背了整个目的这不是正确的方法,即使它有效。请看一下我的最新答案。还有,extractocsv
的代码是什么?为什么它要访问UI对象?@OmarMuscatello在您的回答下面看到我的评论行ExtractToCSV(line,System.IO.Path.GetFileNameWithoutExtension(fi.Name));给出一个错误“调用线程无法访问此对象,因为另一个线程拥有它。”您应该发布ExtractToCSV
函数的代码以获得帮助,或者尝试注释该函数的内容,看看它是否正常工作;只需调试它:)是的,如果我对ExtractToCSV进行注释,它就可以工作,我只是用Dispatcher打包了。调用该部分,似乎一切都很好,谢谢您的帮助。@FirdavsKurbonov,很高兴提供帮助。我很高兴你找到了答案,但这也不应该是正确的解决方案。迭代和执行ExtractToCSV
函数是该方法花费时间的一部分。所有部分都应该在后台线程中执行。不过,这只是一个提示:)