简体   繁体   中英

WPF mvvm background worker UI not updated

I'm using the BusyIndicator in my program, the purpose is to show a busy indicator on the view, while the viewModel is loading data from the database.

*Note: before I added the backgroundworker everything worked perfectly.

My program is build in this way:

I have a view that contains:

<NetworkUI:NetworkView
                        x:Name="networkControl"

                        NodesSource="{Binding Network.Nodes}"
                        ConnectionsSource="{Binding Path=Network.Connections}"


                        MouseDown="networkControl_MouseDown"
                        MouseUp="networkControl_MouseUp"
                        MouseMove="networkControl_MouseMove"

                        />

Where Network.Nodes and Network.Connections are my problem (I need to see them and I don't)

They are binded to the viewModel called mainWindowViewModel, the main method for getting data from Database called ShowSystem:

public void ShowSystem(bool update)
    {



        List<String> interfacesForFlow = new List<String>();
              #region CreateNetworkClasses

        MethodInfo getInterfacesWithGuidToFlow = dbType.GetMethod("getInterfacesWithGuidToFlow");

        #endregion


        MainNet = Common.Model.Network.getNetwork();
        Debug.WriteLine("MainNet.Systems.Count = " + MainNet.Systems.Count);
        if (MainNet.Systems.Count == 0)
            update = true;
        List<String> systemNames = new List<string>();
        if (update)
        {
            if(MainNet.Systems.Count > 0)
                MainNet.Systems.Clear();
            if (this.Network.Nodes.Count > 0)
            {
                this.Network.Nodes.Clear();
                this.Network.Connections.Clear();
            }

            try
            {
                systemNames = (List<String>)getAllSystemMethod.Invoke(sqlDB, null);
                Debug.WriteLine("Success getAllSystemMethod");
            }
            catch (Exception ex)
            {
                logger.addMessage("Error in getAllSystemMethod: " + ex.Message + " Inner: " + ex.InnerException.Message);
                Debug.WriteLine("Error in getAllSystemMethod: " + ex.Message + " Inner: " + ex.InnerException.Message);
            }

            #region CreateSystems
            foreach (var sysName in systemNames)
            {
                #region Intializating
                ObservableCollection<Common.Model.Enum> enums = new ObservableCollection<Common.Model.Enum>();
                ObservableCollection<Common.Model.Struct> structs = new ObservableCollection<Common.Model.Struct>();
                ObservableCollection<Common.Model.Interface> interfaces = new ObservableCollection<Common.Model.Interface>();
                //List<Model.Enum> enums = new List<Model.Enum>();
                //List<Model.Struct> structs = new List<Model.Struct>();
                //List<Model.Interface> interfaces = new List<Model.Interface>();

                int systemId = -1;
                Object[] getSystemIdParams = new Object[1];
                getSystemIdParams[0] = sysName;
                try
                {
                    systemId = (int)getSystemId.Invoke(sqlDB, getSystemIdParams);
                    Debug.WriteLine("Success getSystemId systemId = " + systemId);
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSystemId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSystemId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }

                List<int> sysEnumsIds = new List<int>();
                List<int> sysStructsIds = new List<int>();
                List<int> sysInterfacesIds = new List<int>();

                Object[] getSysEnumsIdParams = new Object[1];
                getSysEnumsIdParams[0] = systemId;
                try
                {
                    sysEnumsIds = (List<int>)getSysEnumsId.Invoke(sqlDB, getSysEnumsIdParams);      //return List<int> all system Enums ids
                    if (sysEnumsIds.Count > 0)
                        Debug.WriteLine("Success getSysEnumsId first count is " + sysEnumsIds.Count);
                    else
                        Debug.WriteLine("success getSysEnumsId but no ids found");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysEnumsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysEnumsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }


                Object[] getSysStructsIdParams = new Object[1];
                getSysStructsIdParams[0] = systemId;
                try
                {
                    sysStructsIds = (List<int>)getSysStructsId.Invoke(sqlDB, getSysStructsIdParams);
                    if (sysStructsIds.Count > 0)
                        Debug.WriteLine("success getSysStructsId count = " + sysStructsIds.Count);
                    else
                        Debug.WriteLine("success getSysStructsId but no ids found");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysStructsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysStructsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }


                Object[] getSysInterfacesIdParams = new Object[1];
                getSysInterfacesIdParams[0] = systemId;
                try
                {
                    sysInterfacesIds = (List<int>)getSysInterfacesId.Invoke(sqlDB, getSysInterfacesIdParams);
                    if (sysInterfacesIds.Count > 0)
                        Debug.WriteLine("Success getSysInterfacesId count = " + sysInterfacesIds.Count);
                    else
                        Debug.WriteLine("success getSysInterfacesId but no ids found");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysInterfacesId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysInterfacesId: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }
                #endregion



                #region GetInterfaces
                foreach (var @interface in sysInterfacesIds)        //get interface
                {

                    ObservableCollection<Common.Model.Message> messages = new ObservableCollection<Common.Model.Message>();
                    ObservableCollection<Common.Model.Definition> definitions = new ObservableCollection<Common.Model.Definition>();
                    ObservableCollection<Common.Model.Include> includes = new ObservableCollection<Common.Model.Include>();

                    List<int> includesIds = new List<int>();
                    List<int> definitionsIds = new List<int>();
                    List<int> messagesIds = new List<int>();


                    #region getIncludes
                    Object[] getIncludesIdsParams = new object[1];
                    getIncludesIdsParams[0] = @interface;
                    try
                    {
                        includesIds = (List<int>)getIncludesIds.Invoke(sqlDB, getIncludesIdsParams);
                        Debug.WriteLine("Success getIncludesIds " + includesIds.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getIncludesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getIncludesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }

                    foreach (var id in includesIds)
                    {
                        Object[] getIncludeParams = new object[1];
                        getIncludeParams[0] = id;
                        string includeName = "";
                        try
                        {
                            includeName = (string)getInclude.Invoke(sqlDB, getIncludeParams);
                            Debug.WriteLine("Success get include name = " + includeName);
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }
                        includes.Add(new Common.Model.Include(includeName));
                    }
                    #endregion

                    #region getdefinitions
                    Object[] getdefinitionsIdsParams = new object[1];
                    getdefinitionsIdsParams[0] = @interface;
                    try
                    {
                        definitionsIds = (List<int>)getDefinitionsIds.Invoke(sqlDB, getdefinitionsIdsParams);
                        Debug.WriteLine("Success getDefinitionsIds " + definitionsIds.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getDefinitionsIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getDefinitionsIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }

                    foreach (var id in definitionsIds)
                    {
                        List<Object> definition = new List<object>();

                        Object[] getDefinitionParams = new object[1];
                        getDefinitionParams[0] = id;
                        string includeName = "";
                        try
                        {
                            definition = (List<Object>)getDefinition.Invoke(sqlDB, getDefinitionParams);
                            Debug.WriteLine("Success getDefinisions " + definition[0]);
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }

                        definitions.Add(new Common.Model.Definition(Convert.ToString(definition[0]), Convert.ToInt32(definition[1])));

                    }
                    #endregion


                    Object[] getInterfaceFromIdParam = new Object[1];
                    getInterfaceFromIdParam[0] = @interface;
                    List<Object> tempInterface = new List<object>();
                    try
                    {

                        tempInterface = (List<Object>)getInterfaceFromId.Invoke(sqlDB, getInterfaceFromIdParam);

                        Debug.WriteLine("Success getInterfaceFromId " + tempInterface.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getInterfaceFromId : " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getInterfaceFromId : " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }
                    interfaces.Add(new Common.Model.Interface(messages, definitions, includes, Convert.ToString(tempInterface[0]), Convert.ToString(tempInterface[1]), Convert.ToInt32(tempInterface[2]), Convert.ToInt32(tempInterface[3]), Convert.ToBoolean(tempInterface[4])));
                    Debug.WriteLine("Success adding new interface: " + interfaces.Last().Name);

                }

                #endregion

                #region InputOutputNumber
                List<int> inputs = new List<int>();
                List<int> outputs = new List<int>();

                int inputCount = 0;
                int outputCount = 0;

                Object[] getSysInputNumParams = new Object[1];
                getSysInputNumParams[0] = systemId;
                try
                {
                    inputs = (List<int>)getSysInputs.Invoke(sqlDB, getSysInputNumParams);
                    if (inputs != null)
                    {
                        inputCount = inputs.Count;
                        Debug.WriteLine("Success getSysInputNum inputs = " + inputCount);
                    }
                    else
                        Debug.WriteLine("Success getSysInputNum inputs = 0");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysInputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysInputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }


                Object[] getSysOutputNumParams = new Object[1];
                getSysOutputNumParams[0] = systemId;
                try
                {
                    outputs = (List<int>)getSysOutputs.Invoke(sqlDB, getSysOutputNumParams);
                    if (outputs != null)
                    {
                        outputCount = outputs.Count;
                        Debug.WriteLine("Success getSysOutputNum outputs = " + outputCount);
                    }
                    else
                        Debug.WriteLine("Success getSysOutputNum outputs = 0");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in getSysOutputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in getSysOutputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
                }
                #endregion

                Common.Model.System system = null;
                try
                {
                    system = new Common.Model.System(interfaces, enums, structs, sysName, inputCount, outputCount, inputs, outputs);
                    Debug.WriteLine("Success adding new system");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in creating new system: " + ex.Message);
                    Debug.WriteLine("Error in creating new system: " + ex.Message);
                }
                MainNet.Systems.Add(system);
                Debug.WriteLine("Done! you now have a new system with: " + interfaces.Count + " interfaces And " + enums.Count + " Enums and " + structs.Count + " Structs, The name is: " + sysName + " numOfInput: " + inputCount + " numOfOutput: " + outputCount);
            #endregion


            }
        #endregion
            }

            #region addNodesToUi

             //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ));

            try
            {
                //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ));

                Debug.WriteLine("Success creating new nodeViewModel");
            }
            catch (Exception ex)
            {
                logger.addMessage("Error in creating new nodeViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
                Debug.WriteLine("Error in creating new nodeViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
            }
            int width = 0;
            int height = 0;

            foreach (var system in MainNet.Systems)
            {
                Debug.WriteLine("inside Foreach in system: " + system.Name + " interface " + system.Interfaces.Count + " structs " + system.Structs.Count);
                if (nodes == null)
                    Debug.WriteLine("FUUUCCKKKK!");
                try
                {
                    Debug.WriteLine("Before add node");
                    try
                    {
                        Debug.WriteLine("trying to add: " + system.Name + " " + system.InputNum + " " + system.OutputNum + " " + system.Interfaces.Count + " " + system.Enums.Count + " " + system.Structs.Count);
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => nodes.Add(CreateNode(system.Name, new Point(width, height), false, system.InputNum, system.OutputNum, system.Interfaces, system.Enums, system.Structs, update))));

                    }

                    catch (Exception ex)
                    {
                        logger.addMessage("Error adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }
                    Debug.WriteLine("Success adding new node to list");
                }
                catch (Exception ex)
                {
                    logger.addMessage("Error in adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                    Debug.WriteLine("Error in adding new node to list " + ex.Message + " Inner: " + ex.InnerException.Message);
                }
                width += 150;
                if (width >= 700)
                {
                    width = 0;
                    height += 100;
                }
            }

            if (MainWindow.IsFlow)
            {
                Object[] getInterfacesWithGuidToFlowParam = new Object[1];
                getInterfacesWithGuidToFlowParam[0] = MainWindow.GuidToFlow;

                    try
                    {
                        interfacesForFlow = (List<String>)getInterfacesWithGuidToFlow.Invoke(sqlDB, getInterfacesWithGuidToFlowParam);

                        Debug.WriteLine("Success getInterfacesWithGuidToFlow " + interfacesForFlow.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getInterfacesWithGuidToFlow : " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getInterfacesWithGuidToFlow : " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }

            }

            foreach (var system in MainNet.Systems)
            {
                if (system.OutputNum > 0)       //this system has an output connector
                {
                    int i = 0;
                    foreach (var outId in system.Outputs)       //loop throw all systems ids that current system is connected to 
                    {
                        Debug.WriteLine("out id = " + outId);
                        ConnectionViewModel connection = null;
                        try
                        {
                            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection = new ConnectionViewModel()));

                            Debug.Write("Success creating new ConnectionViewModel");
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in creating new ConnectionViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in creating new ConnectionViewModel " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }
                        Object[] getSystemNameParams = new Object[1];
                        getSystemNameParams[0] = outId;
                        string destSystemName = "";
                        try
                        {
                            destSystemName = (String)getSystemName.Invoke(sqlDB, getSystemNameParams);
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in getSystemName: " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in getSystemName: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }

                        NodeViewModel sourceItem = null;
                        NodeViewModel destItem = null;
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => sourceItem = nodes.Find(x => x.Name == system.Name)));

                        //int sourceId = nodes.FindIndex(sourceItem);
                        Debug.Write("Success creating new sourceItem");
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem = nodes.Find(x => x.Name == destSystemName)));

                        Debug.Write("Success creating new destItem");
                        try
                        {
                            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem.InputSystems.Add(sourceItem.Name)));

                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error adding input system: " + ex.Message);
                            Debug.Write("Error adding input system: " + ex.Message);
                        }
                        try
                        {
                            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => sourceItem.OutputSystems.Add(destItem.Name)));

                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error adding OutputSystems: " + ex.Message);
                            Debug.Write("Error adding OutputSystems: " + ex.Message);
                        }
                        Debug.Write("Success bah");
                        //int destId = nodes.FindIndex(destItem);


                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.SourceConnector = sourceItem.OutputConnectors[i++]));

                        Debug.Write("Success bah");
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.DestConnector = destItem.InputConnectors[destItem.InputConnectors.Count - 1]));

                        Debug.Write("Success bah");

                        // Add the connection to the view-model.
                        //
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.REGULAR));
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => this.Network.Connections.Add(connection)));


                        //Debug.Write("Success bah");
                        if (MainWindow.IsFlow)
                        {
                            Debug.WriteLine("inside IsFlow!");

                            foreach (var @interface in interfacesForFlow)
                            {
                                String[] systems = @interface.Split('_');
                                Debug.WriteLine("Flow from: " + systems[0] + " To " + systems[1]);
                                if(systems[0].Equals(sourceItem.Name) && systems[1].Equals(destItem.Name))
                                    Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.FLOW));

                            }                                 

                        }
                    }
                }
            }
            #endregion

    }

And this method is being called from the backgroundWorker DoWork method, these all the backgroundWorker references:

public MainWindowViewModel()
    {
        //
        // Create a network, the root of the view-model.
        //

        Network = new NetworkViewModel();
        nodes = new List<NodeViewModel>();
        //ShowSystem(false);
        bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw.RunWorkerAsync(false);



        //create networkt according to classes created
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => this.IsBusy = false));
        this.IsBusy = false;
        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => OnPropertyChanged("Network")));
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {

        //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ));
        this.BusyContent = "Please Wait...";
        this.IsBusy = true;
        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ShowSystem((bool)e.Argument)));
    }

You have not implemented your BackgroundWorker correctly, despite me already providing you with a link to see how it should be implemented in the comments:

Progress Bar update from Background worker stalling

You're not even calling your ShowSystem method from the BackgroundWorker , so how do you expect to get any data?:

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    //You should only update UI properties from here using Dispatcher.CurrentDispatcher
    this.BusyContent = "Please Wait...";
    this.IsBusy = true;
    Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => OnPropertyChanged("Network")));
    //This runs on the background thread so this is where you do long running process
    ShowSystem(false);
}

You clearly haven't learned how to use a BackgroundWorker yet, so that is what you should be doing, rather than coming here and asking duplicate questions. I already gave you a link to one example of the correct implementation of a BackgroundWorker and you can find another in the BackgroundWorker Class page on MSDN.

I trust that will be enough to get you going again.

Do the UI work in the UI thread, using the dispatcher. See here for more information. So basically, anything that has something to do with a UI control needs to be dispatched to the UI thread.

You have to invoke method in main thread from doWork which is running in separate thread in order to update UI.

I'd suggest to have a look at http://msdn.microsoft.com/en-us/library/dd460693(v=vs.110).aspx which is available in .NET4 and above. (Have a look at Task specifically)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM