![](/img/trans.png)
[英]C# BackgroundWorker.ProgressChanged not fired immediately after ReportProgress is called
[英]C# BackgroundWorker ProgressChanged doesn't get fired until end of function
我的班上有一个内部有一些循环的方法。 此方法的主要目的是转换一些文件,因此我在表单中放置了一个进度条,该进度条在转换完每个文件后应进行更新。
我尝试了所有可能的组合,并且阅读了所有可能的内容,但无法解决此问题。
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 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.