我有一个主UI,做了一些耗时的工作。当它正在执行时,我想打开第二个表单,其中包含一个进度条(选框样式)以指示"正在处理它"。
我看到有人把这个耗时的任务放在BackgroundWorker
中,但是,我想在主UI线程中运行。
耗时的任务将在MainForm
中执行。我想重复使用进度条进行各种处理,因此我正在编写第二个表单ProgressBarForm
,其中包含BackgroundWorker
,它会在显示进度条的同时启动_mainWork
,并在ProgressBarForm
完成时停止并关闭_mainWork
。
因为表单是模态,我想在ProgressBarForm
中显示BackgroundWorker
,以便不阻止MainForm
。
请注意,我mainForm
中 <{1}}正在运行BackgroundWorker
。我的backgroundWorker只显示表单,可能会报告一个计时器。
public partial class ProgressBarFom : UControl
{
public delegate void MainWork();
private MainWork _mainWork;
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//progressBar.Hide();
this.OnClose(sender, e);
//
backgroundWorker.Dispose();
}
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
//show this ProgressBarForm
this.ShowDialog();
//stop backgroundWorker
//calling this.Close() in RunWorkerComplete
if (backgroundWorker.CancellationPending == true)
{
e.Cancel = true;
return;
}
}
public void CallProgressBar(object sender, EventArgs e)
{
//progressBar.Show();
backgroundWorker.RunWorkerAsync();
_mainWork();
if (backgroundWorker.IsBusy)
backgroundWorker.CancelAsync();
}
}
在MainForm中,我传递的是mainwork并调用ExecWithProgressBar
private void ExecWithProgressBar()
{
ProgressBarFom .MainWork mainWork = new ProgressBarFom .MainWork(ProgressBarMainWork);
ProgressBarFom prBar = new ProgressBarFom (mainWork);
prBar.CallProgressBar(null, null);
}
我遇到的一些问题
在DoWork内部,会出现相同的模态问题。 ShowDialog()将阻塞该线程,因此我永远不会检查CancellationPending以关闭ProgressBarForm。
ProgressBarForm在mainWork之后启动。我想当我调用CallProgressBar时,backgroundWorker应该在我的mainWork之前启动。
RunWorkerComplete中是否需要worker.Dispose()?
在Worker中运行mainWork是一个更好的选择吗?为什么?我决定让主线程运行这个不干扰正常流程,主线程中的内容将保留在主线程中,进度条就像一个插件。如果我们把它带给工人,我们还需要另一个线程来进行进度条吗?
答案 0 :(得分:0)
除非你做了一些非常丑陋的黑客攻击(比如在应用程序中运行多个消息循环),否则如果运行主窗口的线程忙,则无法显示对话框。所有对话框都使用相同的线程来完成WinForms中的显示更新。实际上,他们甚至必须在同一个线程上运行。
使用Application.DoEvents()
有一个(有时是可接受的)hack,但我也不会使用它,因为它也会让你遇到很多问题。
所以简单的答案是:这不起作用。使用后台工作程序进行冗长的处理。