C#后台工作程序在第二次运行时冻结UI

时间:2012-06-14 17:54:46

标签: c# 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();

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

我不知道为什么第二次这不起作用。在后台工作程序运行之前或之后是否需要执行某些操作以确保它不会阻止UI线程?

谢谢!

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

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

在backgroundworker的DoWork中调用此对象的函数中,可以访问几个静态类。这会导致任何类型的线程问题吗?

2 个答案:

答案 0 :(得分:3)

您可以通过两种方式使用BackgroundWorker

  1. 将其从工具箱中删除到表单并在属性窗口中设置其属性和事件。

  2. 以编程方式定义。

  3. 可能你混合了两种方法。


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

    backgroundWorker1.RunWorkerAsync();
    

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

    中设置worker
    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部分的工具箱中找到的大多数或所有组件,同样的注意事项也适用。

答案 1 :(得分:0)

如果可能,请尝试使用Reactive extensions ... 它非常适合异步处理。