3

在我的 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 线程?

谢谢!

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

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

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

4

2 回答 2

3

您可以通过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

于 2012-06-14T18:08:47.780 回答
0

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

于 2012-06-14T18:16:50.570 回答