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 调用之前添加一些代码,以警告用户后台正在发生某些事情:)
我在 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 调用之前添加一些代码,以警告用户后台正在发生某些事情:)