WPF mvvm backgroundworker UI显示不同的结果

问题描述:

所以最后我设法创建了一个可以正常工作的BackgroundWorker.

So finally i managed to create a working BackgroundWorker.

我使用ReportProgress方法以这种方式更新了UI元素:

I used the ReportProgress method to updated UI elements in this way:

 bw.ReportProgress(1, node);
 bw.ReportProgress(2, connection);
 bw.ReportProgress(3);
 bw.ReportProgress(4, system);

其中连接是模型对象,这是我的进度方法:

Where the connection is a model Object, this is my progress method:

 void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (e.ProgressPercentage == 1)       //update nodes
        {
            this.Network.Nodes.Add((NodeViewModel)e.UserState);
        }
        if (e.ProgressPercentage == 2)       //update connections
        {
            this.Network.Connections.Add((ConnectionViewModel)e.UserState);
        }
        if (e.ProgressPercentage == 3)
        {
            this.Network.Connections.Clear();
            this.Network.Nodes.Clear();
        }
        if (e.ProgressPercentage == 4)
        {
            MainNet.Systems.Add((Common.Model.System)e.UserState);
        }
    }

我有多个对象要更新,所以我使用百分比作为过滤器.

I have multiple objects to update so I used the percentage as a filter.

每次运行代码时,我都会得到不同的结果,就像某些数据无法在用户界面中正确呈现一样

I'm getting different results every time i run the code, as if some of the data is not rendered correctly in the UI

UI的正确形式:

不正确:

如果您需要同步工作人员以避免重入或竞赛,则有几种不同的方法.您可以尝试这样的方法...

If you need to synchronize your worker(s) to avoid reentrancy or a race, there are several different ways. You can try an approach like this...

    private static void ManageBackgroundWorkers()
    {
        BackgroundWorker backgroundWorker1 = new BackgroundWorker();
        BackgroundWorker backgroundWorker2 = new BackgroundWorker();
        BackgroundWorker backgroundWorker3 = new BackgroundWorker();
        backgroundWorker1.DoWork += (s, a) =>
        {
            /* do stuff*/
        };
        backgroundWorker2.DoWork += (s, a) =>
        {
            /* do some more stuff*/
        };
        backgroundWorker3.DoWork += (s, a) =>
        {
            /* do even more different stuff*/
        };
        backgroundWorker1.RunWorkerCompleted += (s, a) =>
        {
            //this.Network.Nodes.Add((NodeViewModel)e.UserState);
            backgroundWorker2.RunWorkerAsync();
        };
        backgroundWorker2.RunWorkerCompleted += (s, a) =>
        {
            //this.Network.Connections.Add((ConnectionViewModel)e.UserState);
            backgroundWorker3.RunWorkerAsync()
        };
        backgroundWorker3.RunWorkerCompleted += (s, a) =>
        {
            // finish remaining tasks here
        };
        /* start the queue */
        backgroundWorker1.RunWorkerAsync();
    }

每个工作程序都发出完成信号,其事件处理程序仅启动该系列中的下一个工作程序.这与您拥有的内容没有太大的区别,但是它重新打包了您使用"Percentage"属性所使用的步骤.无论如何,百分比确实是一个糟糕的州代表.重构代码大约需要5分钟.

Each worker signals a completion and its event handler simply starts the next worker in the series. It is not a massive difference in what you have, but it repackages the steps that you were using the 'Percentage' property for. Percentage is really a bad proxy for state anyway. Refactoring your code should take about 5 minutes.

另一种方法是使用一个ManualResetEvent来检测回调,该回调在每次调用时发出信号.每次调用ReportProgress处理程序后,都会在工作进程中等待ManualResetEven.混乱,模块化程度较低,但确实可行.

An alternative method is to instrument the callback with an ManualResetEvent that signals each time it is called. And the ManualResetEven is waited upon in the worker after each call to the ReportProgress handler. Messier, less modular, but indeed workable.