使用.NET 4.0,我有一个宿主应用程序,它解析csv文件,对每行数据进行说明,并通过WCF回调将其作为类型返回给我的客户端。这部分工作正常。我开始遇到麻烦的地方是当我尝试将该类型或类型集合添加到MainWindow中的ObservableCollection时。
所以这......
public class MyServiceCallback : IMyServiceCallback
{
//List<Location.LocationData> lastData = new List<Location.LocationData>();
//Dictionary<string, Location.LocationData> lastData = new Dictionary<string,Location.LocationData>();
//Network exposed Callback method which recieves Host/Client common data type
//Note: Ought to be an interface and not a class type, but not needed for a small project
public void OnCallback(Location.LocationData[] t)
{
//if(t.Where(x=>x.Frequency == lastData[
//foreach (Location.LocationData d in t)
//{
// lastData.Add(d.Frequency, d);
//}
//Call static method on MainWindow to pass the collection of LocationData to UI bound LocationList
if(!(t.Length == 0))
Client.MainWindow.SetLocationList(t.ToList());
}
}
从WCF主机调用,而SetLocation(t.ToList())调用此...
public partial class MainWindow : Window
{
private static MTObservableCollection<Location.LocationData> locationList = new MTObservableCollection<Location.LocationData>();
public static MTObservableCollection<Location.LocationData> LocationList
{
get { return locationList; }
set { locationList = value; }
}
public static void SetLocationList(List<Location.LocationData> hostPushedLocationData)
{
//Clear previous location data
LocationList.Clear();
System.Threading.Thread.SpinWait(1);
//Add the pushed data to the bound collection to be displayed
hostPushedLocationData.ForEach(data => { LocationList.Add(data); System.Threading.Thread.SpinWait(1); });
}
}
如果我使用普通的ObservableCollection,这根本不起作用,因为我无法从WCF线程更新集合。
如果我用这个扩展ObservableCollection ......
public class MTObservableCollection<T> : ObservableCollection<T>
{
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler CollectionChanged = this.CollectionChanged;
if (CollectionChanged != null)
foreach (NotifyCollectionChangedEventHandler nh in CollectionChanged.GetInvocationList())
{
DispatcherObject dispObj = nh.Target as DispatcherObject;
if (dispObj != null)
{
Dispatcher dispatcher = dispObj.Dispatcher;
if (dispatcher != null && !dispatcher.CheckAccess())
{
dispatcher.BeginInvoke(
(Action)(() => nh.Invoke(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
DispatcherPriority.DataBind);
continue;
}
}
nh.Invoke(this, e);
}
}
}
我在这里找到:Where do I get a thread-safe CollectionView?
我间歇性地收到了这个错误:
我使用此版本时遇到异常,但在使用Jonathan提供的版本时却没有。有没有人有想法为什么会这样?这是我的InnerException:抛出此异常,因为名为'OrdersGrid'的控件'System.Windows.Controls.DataGrid Items.Count:3'的生成器收到了与Item的当前状态不一致的CollectionChanged事件序列采集。检测到以下差异:累计计数2与实际计数3不同。[累计计数为(上次重置计数+ #Adds - 自上次重置后#Removes)
在链接帖子中提及。
我也经常遇到这个错误:索引超出了范围。
如果有人可以帮助或指出我正确的方向,我需要对此集合扩展做什么来解决这个问题,我将不胜感激。此外,如果我使用.NET 4.5而不是4.0来解决这个问题吗?
非常感谢!
答案 0 :(得分:0)
您将通过Dispatcher.BeginInvoke()
解雇您的收藏更改事件。在您安排活动的时间和事件实际触发的时间之间,该集合可能会多次更改。基于异常消息,听起来这正是发生的事情。
不安排稍后提出的更改事件;它们意味着立即被提升。