Threadcrossing ObservableCollection和DataGrid ->竞态条件

本文关键字:条件 ObservableCollection DataGrid Threadcrossing | 更新日期: 2023-09-27 18:08:28

我有以下问题。我有一个USB设备在串行端口发送XML流。我将这个流序列化为List<myObject>。这很好。然后我有一个MTObservableCollection<myObject>,它继承了ObservableCollection<T>并覆盖了OnCollectionChangedCollectionChanged。我必须承认,我在网上找到了这段代码,对我来说很难理解,因为我不是专家。

public class MTObservableCollection<T> : ObservableCollection<T>
{
    public override event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged;
    protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        try
        {
            var eh = CollectionChanged;
            if (eh != null)
            {
                System.Windows.Threading.Dispatcher dispatcher = (from System.Collections.Specialized.NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                                                                  let dpo = nh.Target as System.Windows.Threading.DispatcherObject
                                                                  where dpo != null
                                                                  select dpo.Dispatcher).FirstOrDefault();
                if (dispatcher != null && dispatcher.CheckAccess() == false)
                {
                    dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
                }
                else
                {
                    foreach (System.Collections.Specialized.NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
                        nh.Invoke(this, e);
                }
            }
        }
        catch (Exception exc) { MessageBox.Show(exc.Message); }
    }
}

此集合绑定到数据网格。这个问题只是偶尔发生,这就是为什么我假设一个竞争条件。当我清除集合并向其中添加List<myObject>元素时,我得到一个在下面的代码中未捕获的异常。目前我无法复制它,因为设备在工作。但也许有人会发现代码中的问题。

public MTObservableCollection<DataFile> dataFiles = new MTObservableCollection<DataFile>();
try
{
    this.dataFiles.Clear();
    foreach (DataFile file in (List<DataFile>)data.Data)
    dataFiles.Add(file);
}
catch (Exception exc) { MessageBox.Show(exc.InnerException.Message); }

Threadcrossing ObservableCollection和DataGrid ->竞态条件

我试图找到一个解决方案。我使用计时器而不是SerialPot,只是为了有第二个线程,并在计时器回调中向集合添加了几个项目。我按照你的提示取了一个普通的ObservableCollection。最后它的工作原理,但请您看看代码,并给出评论,如果有什么要改进。我真的很感激。

private void timerCallback(Object state)
{
   for (int i = 0; i < 64; i++)
       AddElement(this.dataGridFiles, new DataFile("A", "B", "C", "D"));
}
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.timer = new System.Threading.Timer(this.timerCallback, true, 1000, System.Threading.Timeout.Infinite);
}
delegate void AddElementDelegateType(DataGrid dg, DataFile df);
AddElementDelegateType AddElementDelegate = (a, b) => ((ObservableCollection<DataFile>)(a.ItemsSource)).Add(b);
private void AddElement(DataGrid dg, DataFile df)
{
    if (!dg.Dispatcher.CheckAccess())
    {
        Action<DataGrid, DataFile> act = new Action<DataGrid, DataFile>((a, b) => AddElement(a, b));
        dg.Dispatcher.Invoke(act, new object[] { dg, df });
    }
    else
        ((ObservableCollection<DataFile>)(dg.ItemsSource)).Add(df);
}