我的类中有一个方法,里面有一些循环。 这个方法的主要目的是转换一些文件,所以我在表单中放了一个进度条,在每个文件转换后都应该更新。
我尝试了所有可能的组合,并且我阅读了所有可能的内容,但我无法解决这个问题。
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)
触发。
可以请别人解释我为什么并帮助我解决方案吗?
谢谢!
答案 0 :(得分:1)
目前,转换不是由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
类的示例了解其他详细信息:How to: Implement a Form That Uses a Background Operation, MSDN。