c# BackgroundWorker ProgressChanged在函数结束前不会被触发
本文关键字:结束 BackgroundWorker ProgressChanged 函数 | 更新日期: 2023-09-27 18:17:35
在我的类中有一个方法,里面有一些循环。这个方法的主要目的是转换一些文件,所以我在我的表单中放置了一个进度条,应该在每个文件转换后更新。
我试了所有可能的组合,我读了所有我能读的,但我不能解决这个问题。
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
converterProgressBar.Value = e.ProgressPercentage;
}
只在我的方法的主循环被执行后才会被调用。
这是我的方法
public string Convert()
{
convertBtn.Enabled = false;
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
totalCount = files.length;
bw.RunWorkerAsync();
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
foreach (string file in files)
{
countFile++;
if (chk.Checked)
{
class1.DoJob();
}
using (// some code))
{
using (//some other code))
{
try
{
using (// again some code)
{
// job executing
}
}
catch (exception
{
}
}
}
convertedVideosL.Text = txtToUpdate;
convertedVideosL.Refresh();
}
countFile = countFile + 1;
MessageBox.Show("Done");
countFile = -1;
return outputFile;
}
以下是BackgroundWorker
事件处理程序:
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= totalCount; i++)
{
if (bw.CancellationPending)
{
e.Cancel = true;
}
else
{
int progress = Convert.ToInt32(i * 100 / totalCount);
(sender as BackgroundWorker).ReportProgress(progress, i);
}
}
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
converterProgressBar.Value = e.ProgressPercentage;
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == false)
{
convertedVideosL.Text = "Finished!";
}
else
{
convertedVideosL.Text = "Operation has been cancelled!";
}
}
但是我无法更新每个被转换文件的进度条。等待foreach循环结束,然后调用bw_ProgressChanged
。
如果我把RunWorkerAsync()
在foreach循环中抛出一个异常,说BackgroundWorker
忙,不能执行其他任务。
在我看来很明显,DoWork()
只执行一个for循环,那么它不应该意识到转换正在进行,但ProgressChanged
应该由ReportProgress(progress,i)
触发。
有人能解释一下为什么,帮我解决吗?
谢谢!
当前BackgroundWorker
类型的实例不执行转换。转换应该从DoWork
事件处理程序调用。
请考虑提取与转换相关的功能:
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
foreach (string file in files)
{
// Details...
}
放入单独的方法中。之后,只需从DoWork
事件处理程序调用该方法。
伪代码:
public void StartConversion()
{
...
TWorkerArgument workerArgument = ...;
worker.RunWorkerAsync(workerArgument);
// No message box here because of asynchronous execution (please see below).
}
private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
e.Result = Convert(worker, (TWorkerArgument)e.Argument);
}
private static TWorkerResult Convert(BackgroundWorker worker, TWorkerArgument workerArgument)
{
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
foreach (string file in files)
{
// Details...
worker.ReportProgress(percentComplete);
}
return ...;
}
private void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Show the message box here if required.
}
请适当替换TWorkerArgument
和TWorkerResult
类型
另外,请参考使用BackgroundWorker
类的示例了解更多详细信息:如何:实现使用后台操作的表单,MSDN.