0

我尝试让连接到 ObservaleCollection 的 ListBox 更高效,因此对于数据库查询,我实现了一个 BackgroundWorker 来完成这项工作。然后在这个后台工作人员中,我想向 UI 添加每个 70 毫秒 3 个条目,因此大量条目(比如 100 个)上的 UI 不会被阻止。这是代码:

    void updateTMWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        var MessagesInDB = from MessageViewModel tm in MessagesDB.Messages
                                  where tm.Type.Equals(_type)
                                  orderby tm.Distance
                                  select tm;

        // Execute the query and place the results into a collection.
        Dispatcher.BeginInvoke(() => { MessagesClass.Instance.Messages = new ObservableCollection<MessageViewModel>(); });

        Collection<MessageViewModel> tempM = new Collection<MessageViewModel>();
        int tempCounter = 0;

        foreach (MessageViewModel mToAdd in MessagesInDB)
        {
            if (MessagesClass.Instance.Messages.IndexOf(mToAdd) == -1)
            {
                tempM.Add(mToAdd);
                tempCounter = tempCounter + 1;
            }
            if (tempCounter % 3 == 0)
            {
                tempCounter = 0;
                Debug.WriteLine("SIZE OF TEMP:" + tempM.Count());
                Dispatcher.BeginInvoke(() =>
                {
                    // add 3  messages at once
                    MessagesClass.Instance.Messages.Add(tempM[0]);
                    MessagesClass.Instance.Messages.Add(tempM[1]);
                    MessagesClass.Instance.Messages.Add(tempM[2]);
                });
                tempM = new Collection<MessageViewModel>();
                Thread.Sleep(70);
            } 
        }
        // finish off the rest
        Dispatcher.BeginInvoke(() =>
        {
            for (int i = 0; i < tempM.Count(); i++)
            {
                MessagesClass.Instance.Messages.Add(tempM[i]);
            }
        });            
    }

输出是:

SIZE OF TEMP:3

A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll

在该行中:MessagesClass.Instance.Messages.Add(tempM[0]); 代码尝试访问 tempM 的第一个元素的位置

有什么提示有什么问题吗?为什么我不能访问 tempM 元素,尽管集合大小 > 0?

4

1 回答 1

1

您忘记了线程同步。看看你的代码:

            1: Debug.WriteLine("SIZE OF TEMP:" + tempM.Count());
            Dispatcher.BeginInvoke(() =>
            {
                // add 3  messages at once
                3: MessagesClass.Instance.Messages.Add(tempM[0]);
                MessagesClass.Instance.Messages.Add(tempM[1]);
                MessagesClass.Instance.Messages.Add(tempM[2]);
            });
            2: tempM = new Collection<MessageViewModel>();

tempM已经是null什么时候MessagesClass.Instance.Messages.Add(tempM[0]);被执行了。因此,请使用某种排序或同步对象,例如:

            EventWaitHandle Wait = new AutoResetEvent(false);

            Debug.WriteLine("SIZE OF TEMP:" + tempM.Count());
            Dispatcher.BeginInvoke(() =>
            {
                // add 3  messages at once
                MessagesClass.Instance.Messages.Add(tempM[0]);
                MessagesClass.Instance.Messages.Add(tempM[1]);
                MessagesClass.Instance.Messages.Add(tempM[2]);

                Wait.Set();
            });
            // wait while tempM is not in use anymore
            Wait.WaitOne();

            tempM = new Collection<MessageViewModel>();
于 2012-07-04T13:16:51.490 回答