hs2*_*s2d 6 c# datagrid observablecollection
喜,
在我的应用程序中,我使用DataGrid来显示一些数据.为了让所有东西都能使用线程我正在使用AsyncObservableCollectionDataGrid的DataContext.当我的应用程序启动时,它会在某些文件夹和更新中查找文件AsyncObservableCollection.查找文件是在一个单独的线程上完成的:
Task.Factory.StartNew(() => _cardType.InitAllOrdersCollection())
.ContinueWith((t) => ThrowEvent(), TaskContinuationOptions.None);
Run Code Online (Sandbox Code Playgroud)
所有加载逻辑都在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);
}
Run Code Online (Sandbox Code Playgroud)
FilesToOrders()方法是将新订单添加到的方法AsyncObservableCollection.希望这可以帮助.
小智 5
添加CanUserAddRows="False"到您的 XAML 文件
<DataGrid CanUserAddRows="False"../>
Run Code Online (Sandbox Code Playgroud)
也许我遗漏了一些明显的东西,但是AsyncObservableCollection您发布的链接中的实现对我来说看起来不是线程安全的。
我可以看到它包含在创建者(消费者)线程上触发 CollectionChanged / PropertyChanged 事件的代码,但我没有看到任何同步来使对集合中的项目的访问成为线程安全的。
更新
据我所知,您可以同时发生以下情况,而无需任何同步:
工作线程(生产者)正在插入项目
UI(消费者)线程正在枚举项目
一种可能性可能是修改AsyncObservableCollection.InsertItem调用以SynchronizationContext.Send在消费者线程上插入项目,尽管这当然会对性能产生影响(生产者等待消费者线程完成插入然后再继续)。
另一种方法是使用ObservableCollection仅在消费者线程上访问的标准,并用于SynchronizationContext.Post发布要从生产者线程插入的项目。就像是:
foreach (var dirFile in dirFiles.AsParallel())
{
var order = new Order(dirFile, this, convention);
_synchronizationContext.Post(AddItem, order);
}
Run Code Online (Sandbox Code Playgroud)
...
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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1004 次 |
| 最近记录: |