为什么BackgroundWorker_RunWorkerCompleted不更新GUI?

时间:2010-01-05 15:16:38

标签: c# wpf backgroundworker

我已经在论坛上搜索过了,但是我认为没有问过我的问题......

我使用BackgroundWorker来处理非常耗时的操作。完成此操作后,应将按钮设置为启用,以便用户可以执行其他操作。

我正在使用WPF并且我正在遵循MVVM模式,因此我无法直接访问此按钮。我必须在BackgroundWorker_RunWorkerCompleted事件处理程序中调用一个方法,该方法将表示按钮enabled-state的Property设置为true。

除了一件事之外一切正常:按钮仅在我重新绘制之后重新绘制点击进入窗口(或最大化窗口,...)。多数民众赞成非常烦人,并花了我一整天的时间来摆脱这种行为,但我找不到解决办法......

BackgroundWorker_RunWorkerCompleted事件处理程序如下所示:

    void fileLoadBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
        SetButtonToEnabled(); }

有谁知道如何解决这个问题?

编辑:

该按钮绑定到命令:

<Button Name="btnLoadTargetFile" Command="{Binding Path=LoadTargetCommand}" .../>

这个命令是史密斯在他的博客(http://msdn.microsoft.com/en-us/magazine/dd419663.aspx)中所说的RelayCommand,看起来像这样:

public RelayCommand LoadTargetCommand
    {
        get
        {
            if (loadTargetCommand == null)
            {
                loadTargetCommand = new RelayCommand(param => this.OnRequestLoadFile(BusinessLogic.CustomTypes.TreeType.Target), param => this.CanLoadTarget);
            }
            return loadTargetCommand;
        }
        set { loadTargetCommand = value; }
    }

this.CanLoadTarget由SetButtonToEnabled()设置为true;方法

编辑2:

以下代码“有效”:

fileLoadBackgroundWorker.RunWorkerAsync(argumentList);
while(fileLoadBackgroundWorker.IsBusy)
  System.Windows.Forms.Application.DoEvents();
SetButtonToEnabled();

但这是一种非常危险和丑陋的代码......

2 个答案:

答案 0 :(得分:2)

虽然它没有解释你的问题,你可以尝试添加

System.Windows.Forms.Application.DoEvents();

Dispatcher.Invoke(new Action(delegate { }), DispatcherPriority.Background);

到SetButtonToEnabled函数调用的结尾(将Enabled按钮设置为true后)。看起来后台工作者正在调用Complete事件,但GUI没有刷新。

Here是使用WPF中的Backgroundworker的完整示例。你可能想看看它,并确保你的东西看起来一样。

您还可以查看Asynchronous Threading with Background Worker Object。这是使用Dispatcher和Backgroundworker

的一个很好的例子

WPF Threading Model是另一个值得检查的好消息来源。

答案 1 :(得分:1)

您的问题可能与BackgroundWorker无关。如果直接从主线程调用SetButtonToEnabled方法,您可能会看到相同的行为。将来自RunWorkerAsync的号码替换为SetButtonToEnabled,以对此进行测试。

一些评论者建议您查看INotifyPropertyChanged实施,这听起来不错。