【问题标题】:BackgroundWorker DoWork function is not being called未调用 BackgroundWorker DoWork 函数
【发布时间】:2021-01-03 00:57:27
【问题描述】:

我在我的 C# WinForms 应用程序中创建了一个加载表单,该表单在长流程中显示。 我在我的加载表单中添加了一个进度条,我想更新它以向用户提供一些加载反馈。

在我的加载表单代码中,我创建了一个新的 BackgroundWorker 并添加了 DoWork 和 ProgressChanged 事件处理程序。 问题是没有调用 backgroundWorker_ProgressChanged。我在函数中插入了断点,它们没有被捕获。

我哪里错了?任何帮助表示赞赏。谢谢。

frmLoading:

public frmLoading()
        {
            InitializeComponent();

            //check if bg worker is null
            if (backgroundWorker == null)
            {
                backgroundWorker = new BackgroundWorker();

                backgroundWorker.DoWork += backgroundWorker_DoWork;
                backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;

                
            }

            backgroundWorker.WorkerReportsProgress = true;

            //start
            backgroundWorker.RunWorkerAsync();
        }

backgroundWorker_DoWork:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 100; i++)
            {
                Thread.Sleep(100);
                backgroundWorker.ReportProgress(i);
            }
        }

backgroundWorker_ProgressChanged:

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //update value of progress bar
            progressBar1.Value = e.ProgressPercentage;
            //set the text of the progress bar
            this.Text = e.ProgressPercentage.ToString();
        }

【问题讨论】:

  • 使用调试器,Debug > Windows > Threads,观察主线程在做什么。它必须处于空闲状态,在 Application.Run() 中执行才能执行此事件处理程序。永远不要让它执行昂贵的代码,这是工作线程的工作。
  • BGW 自 2012 年以来已过时,完全被 Task.Run 和 Progress 取代。不过,要定期更新 UI,您只需要a Timer,而不是后台线程。创建一个简单的 Winforms 计时器,在加载时启用它并在完成后禁用它,或者当 ProgressBar 达到最大值时禁用它
  • 谢谢,我会看看 Task.Run。我认为这项工作需要在一个单独的线程上进行,因为我已经在另一个表单的后台运行了大型进程。
  • @PaulAlexander - Task.Run 将在另一个线程上执行。
  • 为什么要检查backgroundWorker == null?当然是null,你在表单的构造函数中。除非那里发生了您没有显示的其他事情,例如尝试以某种方式回收此表单。将backgroundWorker.RunWorkerAsync(); 移动到Form.LoadForm.OnLoad(或OnShown() 以查看表单是否显示已呈现)。如果它没有启动,那么你不会让它启动,因为其他东西阻塞了 UI 线程,所以这行代码永远不会执行。

标签: c# multithreading winforms backgroundworker background-thread


【解决方案1】:

以下是使用 Progress&lt;int&gt;Task.Run 的方法:

public frmLoading()
{
    InitializeComponent();

    IProgress<int> progress = new Progress<int>(p =>
    {
        //update value of progress bar
        progressBar1.Value = p;
        //set the text of the progress bar
        this.Text = p.ToString();
    });

    Task.Run(async () =>
    {
        for (int i = 1; i <= 100; i++)
        {
            await Task.Delay(TimeSpan.FromSeconds(0.1));
            progress.Report(i);
        }
    });
}

我个人更喜欢微软的响应式框架:

public frmLoading()
{
    InitializeComponent();

    Observable
        .Interval(TimeSpan.FromSeconds(0.1))
        .Take(100)
        .ObserveOn(this)
        .Select(p => p + 1)
        .Subscribe(p =>
        {
            //update value of progress bar
            progressBar1.Value = p;
            //set the text of the progress bar
            this.Text = p.ToString();
        });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    • 2023-03-03
    相关资源
    最近更新 更多