【问题标题】:WPF mvvm backgroundWorker busyIndicatorWPF mvvm backgroundWorker busyIndi​​cator
【发布时间】:2014-05-06 20:25:02
【问题描述】:

我在使用 MVVM 模式的程序中使用busyIndicator,我发现后台工作人员和处理视图中绑定的对象存在问题,因此我使用了 Dispacher.Invoke 方法所有使用绑定属性的函数,在我使用 Dispacher 后,busyIndi​​cator 出现了,但是当 backgoundWorker 完成时,我的视图里面没有元素,我做错了什么?

我知道它的代码有点少,但我不知道什么(以及是否)会有所帮助,如有必要,请告诉我,我将使用所需的代码编辑此消息。

编辑:

下面是一些可能有帮助的代码:

这是 BW 的创建,它发生在 viewModel 构造函数上

        bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw.RunWorkerAsync(false);

这是 BW 函数

 void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        this.IsBusy = false;
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        this.BusyContent = "Please Wait...";
        this.IsBusy = true;
        ShowSystem((bool)e.Argument);
    }

showSystem方法很长,我只添加使用UI元素的部分

List<NodeViewModel> nodes = null;
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => nodes = new List<NodeViewModel>()));

int width = 0;
int height = 0;

foreach (var system in MainNet.Systems)
{
    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))));

    width += 150;
    if (width >= 700)
    {
        width = 0;
        height += 100;
    }
}

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

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

}

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 
        {;
            ConnectionViewModel connection = null;
            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection = new ConnectionViewModel()));

            Object[] getSystemNameParams = new Object[1];
            getSystemNameParams[0] = outId;
            string destSystemName = "";

            destSystemName = (String)getSystemName.Invoke(sqlDB, getSystemNameParams);

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

            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem = nodes.Find(x => x.Name == destSystemName)));
            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem.InputSystems.Add(sourceItem.Name)));

            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => sourceItem.OutputSystems.Add(destItem.Name)));

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

            Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.DestConnector = destItem.InputConnectors[destItem.InputConnectors.Count - 1]));

            // 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)));

            if (MainWindow.IsFlow)
            {
                foreach (var @interface in interfacesForFlow)
                {
                    String[] systems = @interface.Split('_');
                    if(systems[0].Equals(sourceItem.Name) && systems[1].Equals(destItem.Name))
                        Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.FLOW));

                }                                 

            }
        }
    }
}

编辑:

这是从数据库中获取数据的部分:

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

                    Object[] getStructFromIdParam = new Object[1];
                    getStructFromIdParam[0] = @struct;
                    List<Object> tempStruct = new List<object>();
                    try
                    {

                        tempStruct = (List<Object>)getStructFromId.Invoke(sqlDB, getStructFromIdParam);

                        Debug.WriteLine("Success getStructFromId " + tempStruct.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getStructFromIdParam : " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getStructFromIdParam : " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }
                    structs.Add(new Common.Model.Struct(Convert.ToString(tempStruct[0]), Convert.ToString(tempStruct[1]), Convert.ToString(tempStruct[2]), fields, bitFields));
                    Debug.WriteLine("Success adding new struct: " + structs.Last().Name);






                }
                #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

                    #region getMessages
                    Object[] getMessagesIdsParams = new object[1];
                    getMessagesIdsParams[0] = @interface;
                    Debug.WriteLine("Trying to get messages for interface #" + @interface);
                    try
                    {
                        messagesIds = (List<int>)getMessagesIds.Invoke(sqlDB, getMessagesIdsParams);
                        Debug.WriteLine("Success getMessagesIds " + messagesIds.Count);
                    }
                    catch (Exception ex)
                    {
                        logger.addMessage("Error in getMessagesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        Debug.WriteLine("Error in getMessagesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                    }

                    foreach (var id in messagesIds)
                    {
                        //List<Model.MType> types = new List<Model.MType>();
                        ObservableCollection<Common.Model.MType> types = new ObservableCollection<Common.Model.MType>();
                        List<int> typesIds = new List<int>();

                        Object[] getMessageTypesIdsParams = new Object[1];
                        getMessageTypesIdsParams[0] = id;
                        try
                        {
                            typesIds = (List<int>)getMessageTypesIds.Invoke(sqlDB, getMessageTypesIdsParams);
                            Debug.WriteLine("Success getMessageTypesIds " + typesIds.Count);
                        }
                        catch (Exception ex)
                        {
                            logger.addMessage("Error in getMessageTypesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                            Debug.WriteLine("Error in getMessageTypesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
                        }
                        foreach (var typeId in typesIds)
                        {
                            List<Object> type = new List<object>();

                            Object[] getTypeParams = new object[1];
                            getTypeParams[0] = typeId;
                            //string includeName = "";
                            try
                            {
                                type = (List<Object>)getType.Invoke(sqlDB, getTypeParams);
                                Debug.WriteLine("Success getType");
                            }
                            catch (Exception ex)
                            {
                                logger.addMessage("Error in getType " + ex.Message + " Inner: " + ex.InnerException.Message);
                                Debug.WriteLine("Error in getType " + ex.Message + " Inner: " + ex.InnerException.Message);
                            }

                            types.Add(new Common.Model.MType((string)type[0], (string)type[1], (string)type[2], (string)type[3], (string)type[4], (string)type[5], (Guid)type[6]));
                            Debug.WriteLine("Success adding new type: " + (string)type[0] + " " + (string)type[1] + " " + (string)type[2] + " " + (string)type[3] + " " + (string)type[4] + " " + (string)type[5] + " " + (Guid)type[6]);
                        }

                        string sourceSystem = "";
                        string destSystem = "";


                        List<Object> message = new List<object>();
                        Object[] getMessageParams = new Object[1];
                        getMessageParams[0] = id;
                        try
                        {
                            message = (List<Object>)getMessage.Invoke(sqlDB, getMessageParams);
                            Debug.WriteLine("Success getMessageParams");

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

                        messages.Add(new Common.Model.Message(types, message[0].ToString(), (int)message[1], message[2].ToString(), message[3].ToString(), message[4].ToString(), message[5].ToString(), message[6].ToString(), message[7].ToString(), message[8].ToString(), message[9].ToString()));
                        Debug.WriteLine("Success adding new Message: " + message[0].ToString() + " " + (int)message[1] + " " + message[2].ToString() + " " + message[3].ToString() + " " + message[4].ToString() + " " + message[5].ToString() + " " + message[6].ToString() + " " + message[7].ToString() + " " + message[8].ToString() + " " + message[9].ToString());

                    }
                    #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

【问题讨论】:

  • 向我们展示您的一些代码
  • 重点是代码很多,哪部分有帮助?
  • 我不确定“我的视图内部没有元素”是什么意思。您能否向我们展示一个示例,说明您如何在代码中使用 Dispatcher.Invoke,以及您的预期结果与实际结果是什么?
  • @Rachel 我用我所有的代码更新了我的消息,预期的结果是一个带有矩形的窗口,实际结果只是一个没有矩形的窗口,出现 BusyIndi​​cator 和他出现的时间与我在获得指标之前必须等待的时间一致
  • 这段代码有用吗?

标签: c# wpf mvvm backgroundworker wpftoolkit


【解决方案1】:

这里的dispatcher使用不正确

Dispatcher 可用于将代码编组到 UI 线程上,如果需要,可以按指定的优先级。代码不会立即执行并返回,而是按照DispatcherPriority 顺序指定的优先级运行。

基本上你的代码在说

  • 创建列表
  • >> 稍后在 UI 线程上填充列表的队列代码
  • 如果列表不为空,执行一些代码

该列表将始终为空,因为填充它的代码尚未运行。它仅在可用时排队运行一次。

执行此操作的正确方法是在后台工作人员上填充数据,然后将结果编组回 UI 线程以填充您的 UI。

请注意,对象只能在创建对象的线程上进行修改。因此,如果您计划稍后在 UI 中使用和/或修改某些对象,您应该会看到如下内容:

  • 创建对象
  • 启动BackgroundWorker获取数据
  • BackgroundWorker 在后台线程上获取数据而不锁定 UI
  • BackgroundWorker 完成并使用 Dispatcher 在 UI 线程上运行代码,该代码将使用结果更新第一步创建的对象

【讨论】:

  • 我不确定我是否完全理解我如何按照您的建议使用 Dispatcher,因为我有很多课程和一些其他项目应该获得这个节点列表,所以我该如何使用它一种确保所有其他人都能够修改列表的方法。你对我的 null 问题有什么解决方案?有没有等待调度程序方法或类似的东西?
  • @Yogevnn 在主 UI 线程上创建您的列表。启动后台工作程序以获取要填充该列表的对象列表。在后台工作线程结束时,使用 Dispatcher 将从后台工作代码中获取的数据分配给在主 UI 线程上创建的列表。此外,如果您将 UI 绑定到对象列表并在运行时修改该列表,您可能希望使用 ObservableCollection&lt;T&gt; 而不是 List&lt;T&gt;,以便 UI 在集合更改时收到更新通知。
  • 谢谢你,我会检查并在它工作后更新
  • 好的,我这样做了,现在列表不为空,我在视图中的问题仍然存在,我没有看到绑定的对象: NodesSource="{Binding Network.Nodes}" ConnectionsSource ="{Binding Path=Network.Connections}" 网络在我的类中作为属性被删除,我按照你所说的对其进行了初始化,从调试窗口(我有很多调试)我看到所有数据都在网络内但由于某种原因,视图没有播种,我在这里错过了什么?
  • @Yogevnn Network 类是否实现INotifyPropertyChanged,并且是ObservableCollection&lt;T&gt; 类型的NodesConnections 属性而不是List&lt;T&gt;
猜你喜欢
  • 2012-09-05
  • 2016-10-31
  • 1970-01-01
  • 2018-07-03
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 2011-04-02
  • 2012-11-28
相关资源
最近更新 更多