c# – WPF DataGrid正在添加额外的“ghost”行
喜,
在我的应用程序中,我使用DataGrid来显示一些数据.为了让所有东西都能使用线程,我使用 Task.Factory.StartNew(() => _cardType.InitAllOrdersCollection()) .ContinueWith((t) => ThrowEvent(),TaskContinuationOptions.None); 其中所有加载逻辑都在InitAllOrdersCollection()方法中. 现在这里的事情变得糟糕,当我出于某种原因启动应用程序时,我在DataGrid中获得了2行具有相同数据,即使集合中有一个项目而文件夹中只有一个文件.如果我在加载文件之前添加一个延迟(Thread.Sleep()最小50ms),那么DataGrid会正确显示所有内容(没有额外的行).延迟必须添加到线程加载文件(使用Task.Factory.StartNew()创建的文件). 有没有人遇到类似的东西或者我还应该尝试其他什么? 编辑:根据要求添加一些代码: public AsyncObservableCollection<IGridItem> OrdersCollection = new AsyncObservableCollection<IGridItem>(); public void InitAllOrdersCollection() { // Thread.Sleep(50); <-- this sleep here fixes the problem! foreach (var convention in FileNameConventions) { var namePatterns = convention.NameConvention.Split(','); foreach (var pattern in namePatterns) { var validFiles = CardTypeExtensions.GetFiles(this.InputFolder,pattern,convention); if (validFiles.Any()) { this.FilesToOrders(validFiles,convention); } } } } public static List<string> GetFiles(string inputFolder,string pattern,FileNameConvention convention) { var files = Directory.GetFiles(inputFolder,pattern); return files.Where(file => IsCorrect(file,convention)).AsParallel().ToList(); } // Adds new order to OrdersCollection if its not there already! private void FilesToOrders(List<string> dirFiles,FileNameConvention convention) { foreach (var dirFile in dirFiles.AsParallel()) { var order = new Order(dirFile,this,convention); if (!this.OrdersCollection.ContainsOrder(order)) { this.OrdersCollection.Add(order); } } } public static bool ContainsOrder(this ObservableCollection<IGridItem> collection,Order order) { return collection.Cast<Order>().Any(c=>c.Filepath == order.Filepath); } FilesToOrders()方法是将新订单添加到AsyncObservableCollection的方法. 解决方法
也许我错过了一些明显的东西,但是你发布的链接中的AsyncObservableCollection实现对我来说看起来不是线程安全的.
我可以看到它包含在创建者(消费者)线程上触发CollectionChanged / PropertyChanged事件的代码,但是我没有看到任何同步来访问集合线程安全中的项目. UPDATE 据我所知,您可以同时发生以下情况,而无需任何同步: > worker(producer)线程正在插入项目 一种可能性是修改AsyncObservableCollection.InsertItem以调用SynchronizationContext.Send以在消费者线程上插入该项,但这当然会对性能产生影响(生产者在继续之前等待消费者线程完成插入). 另一种方法是使用仅在使用者线程上访问的标准ObservableCollection,并使用SynchronizationContext.Post将项目发布到生产者线程中.就像是: foreach (var dirFile in dirFiles.AsParallel()) { var order = new Order(dirFile,convention); _synchronizationContext.Post(AddItem,order); } … void AddItem(object item) { // this is executed on the consumer thread // All access to OrderCollection on this thread so no need for synchnonization Order order = (Order) item; if (!OrdersCollection.ContainsOrder(order)) { OrdersCollection.Add(order); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |