【问题标题】:C# backgroundWorker wait ReportProgressC# backgroundWorker 等待 ReportProgress
【发布时间】:2014-05-09 04:39:59
【问题描述】:

有没有办法“等待”ReportProgress 方法结束?

我正在更新ReportProgress 方法上的列表,在我调用该方法后我正在使用该列表,除非ReportProgress 完成,否则这是错误的。

#region addNodesToUi

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

            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;
            int i = 0;
            ObservableCollection<Common.Model.System> allSystems = new ObservableCollection<Common.Model.System>();
            lock (mainNetLocker)
            {
                allSystems = MainNet.Systems;
            }

            foreach (var system in allSystems.ToList())
            {
                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))));
                        nodes.Add(CreateNode(system.Name, new Point(width, height), false, system.InputNum, system.OutputNum, system.Interfaces, system.Enums, system.Structs, update));
                        //bw.ReportProgress(i++, tempn

                    }

                    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 allSystems.ToList())
            {
                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()));
                            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)));
                        lock (networkLocker)
                        {
                            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)));
                        lock (networkLocker)
                        {
                            destItem = nodes.Find(x => x.Name == destSystemName);
                        }

                        Debug.Write("Success creating new destItem");
                        try
                        {
                            //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem.InputSystems.Add(sourceItem.Name)));
                            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)));
                            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++]));
                        connection.SourceConnector = sourceItem.OutputConnectors[i++];

                        Debug.Write("Success bah");
                        //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.DestConnector = destItem.InputConnectors[destItem.InputConnectors.Count - 1]));
                        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));
                        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))
                                    connection.Type = ConnectionViewModel.ConnectorType.FLOW;
                                    //Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.FLOW));

                            }                                 

                        }
                        lock (networkLocker)
                        {
                            bw.ReportProgress(2, connection);
                        }
                    }
                }
                Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => ww.Close()));

                //bw2.ReportProgress(100);
            }
            #endregio

我无法上传整个方法,这是将节点添加到 UI 的部分,从数据库更新可以在这里看到:Look at the edit below

【问题讨论】:

  • 你能分享一些代码吗?为什么不在 WorkCompleted 上调用它?您是否要等到 DoWork 完全完成?
  • DoWork 正在从该函数调用一个函数 ShowSystem 我已经绑定了我正在更新的 UI 元素,在我更新我需要继续做的元素(列表)之后抛出 ReportProgress对它们的操作(以相同的方法-ShowSystem),我发现我需要等待ReportProgress 结束,以便列表包含所有元素
  • @Miguel,这个问题的代码在前面的问题中stackoverflow.com/questions/23548685/…希望能有所帮助
  • catch (Exception ex) { Debug.Writeline(ex...); } 通常是一个严重的错误,因为这会丢弃重要的诊断信息,然后继续进行,就好像没有出错一样。例如。如果nodes.Add 在你的代码中失败,你抓住它然后尝试使用nodes;那会给你虚假信息。 catch 用于修复错误,Debug 语句不修复错误。学习使用调试器。

标签: c# multithreading backgroundworker


【解决方案1】:

如果您想序列化对您的 ReportProgress 方法的访问并且无法更改工作方法,您可以将 ReportProgress 更改为此...

    private readonly Semaphore _throttle = new Semaphore(1,1);
    void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        try
        {
            _throttle.WaitOne();
            if (e.ProgressPercentage == 1)       //update nodes
            {
                this.Network.Nodes.Add((NodeViewModel)e.UserState);
            }
            else if (e.ProgressPercentage == 2)       //update connections
            {
                this.Network.Connections.Add((ConnectionViewModel)e.UserState);
            }
            else if (e.ProgressPercentage == 3)
            {
                this.Network.Connections.Clear();
                this.Network.Nodes.Clear();
            }
            else if (e.ProgressPercentage == 4)
            {
                MainNet.Systems.Add((Common.Model.System)e.UserState);
            }
        }
        finally
        {
            _throttle.Release();
        }
    }

这种方法为回调添加了一个限制,这将强制调用者等待 ReportProgress 完成。一次只有一个调用者可以进入方法的主体,这是您想要实现的。缺点是队列会阻塞 UI,但无论如何,这个结果在你的问题中是隐含的。

Semaphore docs are here

【讨论】:

  • 哇,这看起来就像我在看的一样!!我立即检查,非常感谢您的帮助!!!!
  • @Yogevnn,无需感谢,请阅读stackoverflow.com/help/someone-answers
  • 不幸的是它仍然无法正常工作:\ 我现在很绝望,但我有一个领先优势,如果我从 DB 更新但当我再次按下显示按钮时,所有 UI 看起来都很棒我不需要从数据库更新,所以我只是显示我已经拥有的模型类,然后由于某种原因 UI 未正确呈现,我将使用所有 showSystem 方法编辑此消息也许你会看到我看不到的东西
  • 我用 addNodesToUI 部分更新了我的消息,并且有一个指向 getFromDB 部分所在位置的链接(抱歉链接,对于一条消息来说太长了)。
  • 好的,所以我有一个更新,UI 问题是别的东西,完全愚蠢,但是当我在调试模式下运行时,我可以看到节点列表只包含 3 个元素,而它应该是在我从数据库中获得的所有 4 个元素上填充了一个 foreach 循环,这是一行:destItem = nodes.Find(x =&gt; x.Name == destSystemName);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多