MainForm中的耗时任务,另一种形式的进度条

时间:2015-03-20 10:35:09

标签: c# multithreading modal-dialog progress-bar progressdialog

我有一个主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);
    }

我遇到的一些问题

  1. 在DoWork内部,会出现相同的模态问题。 ShowDialog()将阻塞该线程,因此我永远不会检查CancellationPending以关闭ProgressBarForm。

  2. ProgressBarForm在mainWork之后启动。我想当我调用CallProgressBar时,backgroundWorker应该在我的mainWork之前启动。

  3. RunWorkerComplete中是否需要worker.Dispose()?

  4. 在Worker中运行mainWork是一个更好的选择吗?为什么?我决定让主线程运行这个不干扰正常流程,主线程中的内容将保留在主线程中,进度条就像一个插件。如果我们把它带给工人,我们还需要另一个线程来进行进度条吗?

1 个答案:

答案 0 :(得分:0)

除非你做了一些非常丑陋的黑客攻击(比如在应用程序中运行多个消息循环),否则如果运行主窗口的线程忙,则无法显示对话框。所有对话框都使用相同的线程来完成WinForms中的显示更新。实际上,他们甚至必须在同一个线程上运行。

使用Application.DoEvents()有一个(有时是可接受的)hack,但我也不会使用它,因为它也会让你遇到很多问题。

所以简单的答案是:这不起作用。使用后台工作程序进行冗长的处理。