C# 后台工作者问题

C# backgroundworker issue

我在 C# 中遇到了后台工作器的问题。 我正在编写一个 dll 文件。

这是我在 VS 2019 中的 Class 库 (.NET Framework) 类型项目中的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace States
{    
    public class ST
    {        
        public static void Read()
        {
            BackgroundWorker bgwMessage = new BackgroundWorker();
            bgwMessage.DoWork += new DoWorkEventHandler(BgwFileOpen_DoWork);
            bgwMessage.RunWorkerAsync();
        }
       
        private static void BgwFileOpen_DoWork(object sender, DoWorkEventArgs e)
        {
            MessageBox.Show("Ran");
        }
    }
}

当我使用 Immediate window 调用 Read() 方法时,后台工作程序 DoWork 方法中的命令不会 运行.逐行调试问题表明 Read() 方法是 运行ning 但它不会以某种方式调用 RunworkerAsync。

*更新1: 启动线程也不起作用:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TradeStates
{
    
    public class ST
    {
        
        public static void Read()
        {
            Thread thr = new Thread(new ThreadStart(MSGshow));
            thr.Start();
        }
        public static void MSGshow()
        {
            MessageBox.Show("Ran");
        }


    }
}

一些事情...

正确实现后台工作者

DoWork 事件被触发一次以执行后台工作,并且不得执行任何访问 UI controls/UI 线程的操作。

您还可以使用另外两个事件。 ProgressChanged 用于报告进度。例如,您可以实施该方法来更新进度条。另一个,我认为您应该感兴趣的是 RunWorkerCompleted。在你的情况下你会有类似

的东西
bgwMessage.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(BgwFileOpen_ShowDialog);
...
private void BgwFileOpen_ShowDialog(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("Ran");
}

一些其他想法

  • 您的后台工作者通常应该是 Form 或其他 winforms class 的 属性,因为 BackgroundWorker 继承自 Component
  • 当后台工作者的父级被释放时,它应该在后台工作者上调用Dispose()

BackgroundWorker Class 文档提供了一个很好的示例,说明如何正确使用 class。

改用线程或任务

如果您必须从 Read() 创建并启动 worker,我建议您改为启动 Thread,并让它在完成后向 UI 线程发送消息.然后您的消息处理程序将启动消息框。

您甚至可以使用 Task,然后向 UI 线程上继续的任务添加一个延续,调用 MessageBox.Show().

即时Window 问题

It appears Immediate window 可能在执行线程时出现问题,或者至少显示 outputs/results 其他线程的 outputs/results,而不是 运行ning .它旨在与您(开发人员)进行交互,而不是作为 运行 应用程序的全功能环境,例如 winforms。

我相信,如果您将 Read() 方法设计为接受正确实施的后台工作程序(即在 Read() 之外创建和设置),然后调用 RunWorkerAsync()Read() 中,消息框应该会按预期弹出——只是您在通过立即 window.

时不会看到它

我建议使用任务。它适用于 4.5 以上的任何 dotnet(4.0 也有额外的包)

using System.Threading.Tasks;
public class ST
{        
    public static async Task Read()
    {
        await Task.Run(() => {
              //Do some big work here
        };
    }               
}

然后例如在您的按钮点击事件中调用:

private async void Button_Click(object sender, EventArgs e)
{
   await ST.Read();
   MessageBox.Show("Ran");
}

这不会在您执行大型读取任务时冻结您的视图,并且会在完成后返回到 Button_Click 函数的下一行以显示对话框结果。
您甚至可以在 Read 调用之前添加一些代码,以警告用户后台正在发生某些事情:)