Threadcrossing ObservableCollection和DataGrid ->竞态条件
本文关键字:条件 ObservableCollection DataGrid Threadcrossing | 更新日期: 2023-09-27 18:08:28
我有以下问题。我有一个USB设备在串行端口发送XML流。我将这个流序列化为List<myObject>
。这很好。然后我有一个MTObservableCollection<myObject>
,它继承了ObservableCollection<T>
并覆盖了OnCollectionChanged
和CollectionChanged
。我必须承认,我在网上找到了这段代码,对我来说很难理解,因为我不是专家。
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); }
我试图找到一个解决方案。我使用计时器而不是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);
}