C# 后台辅助角色在第二次运行时冻结 UI

本文关键字:第二次 运行时 冻结 UI 角色 后台 | 更新日期: 2023-09-27 18:37:18

在我的UI中,按下按钮时,将执行以下代码:

backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.RunWorkerAsync();

这在第一次就很好用。当我点击按钮(然后被禁用)时,我仍然可以在执行后台任务时移动窗口并单击内容。但是当后台工作线程完成(按钮再次启用)并且我再次按下它时,后台工作程序将运行,但我不再控制窗口。

我不知道为什么第二次不起作用。在后台辅助角色运行之前或之后,我需要执行哪些操作以确保它不会阻止 UI 线程?

谢谢!

编辑:在后台工作线程进度更改处理程序中,我更新进度条和文本标签,显示后台工作线程的距离。它们不断更新,永远不会冻结。但是当我尝试拖动窗口或单击其他控件时,它们只会定期响应。

后台工作线程访问作为 UI 线程中的全局变量的类的实例。这个想法是实例化对象,从后台工作线程的 DoWork 内部运行对象执行的长函数,然后在后台工作线程完成后访问对象以查看结果。可以这样做吗?

在后台工作者的 DoWork 中调用的此对象的函数中,访问了几个静态类。这会导致任何类型的线程问题吗?

C# 后台辅助角色在第二次运行时冻结 UI

您可以通过

两种方式使用该BackgroundWorker

  1. 通过将其从工具箱拖放到窗体并在属性窗口中设置其属性和事件。

  2. 通过以编程方式定义它。

可能您混合了这两种方法。


如果您使用了第一种方法,则删除所有初始化代码(表单会自动为您执行!)并仅调用

backgroundWorker1.RunWorkerAsync();

如果要使用第二种方法,请不要将其放在窗体上。而是将其声明为成员变量。能够将其作为组件添加到窗体的唯一目的是启用通过属性窗口设置属性和事件。BackgroundWorker不需要表单中的任何内容,可以完全独立于任何形式使用。然后在窗体构造函数中设置工作线程

backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged +=
    new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted +=
    new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

并且仅在按钮单击处理程序中执行此操作

backgroundWorker1.RunWorkerAsync();

对于在Components部分的工具箱中找到的大多数或所有组件,相同的注意事项也是如此。

如果可能的话,尝试使用反应式扩展...它非常适合异步处理。