我有我的类中有一些内部循环的方法。 这个方法的主要目的是转换一些文件,所以我在我的表单中放置了一个进度条,在每个文件转换后应该更新。C#BackgroundWorker ProgressChanged不会被触发,直到函数结束
我尝试了所有可能的组合,并且阅读了所有可能的内容,但无法解决此问题。
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存在误解。该工作应该发生在BackgroundWorker内部(即将逻辑从Convert转换为bw_DoWork)。在循环的每次迭代(在DoWork!内部)触发ReportProgress方法。 – syazdani
你能否详细说明一下?因为我试图运行DoWork中的代码,但是如何在循环之后触发ReportProgress方法?我在哪里放RunWorkerAsync? –
有很多事情,你需要改变,以使其工作。您应该在bw_DoWork中运行Convert方法,但不应该访问内部控件(如chk,convertedVideosL),也不应该使用MessageBox-es。你应该从那里调用bw.ReportProgress并在bw_ProgressChanged中处理它,你可以在这里更新你的UI。坦率地说,使用'async/await'完成所有这些工作会容易得多,你有这个选择吗? –