我在带线程的DataView上正确使用了RowFilter吗

本文关键字:RowFilter 线程 DataView | 更新日期: 2023-09-27 18:26:39

EDIT:我使用的是VS2008,.NET 3.5

我有一个DataTable,它被填充在DataView中并传递到CollectionView中。

   DataTable newLeadTable = new DataTable();
   myConnection.Open();
   dbAdpater.Fill(newLeadTable);
   this.LeadDataView = new DataView(newLeadTable);
   this.LeadsCollectionView = 
   CollectionViewSource.GetDefaultView(this.LeadDataView);

然后,用于显示数据的DataGrid绑定到this.LeadsCollectionView

用户在视图中输入筛选文本后,ViewModel将执行此方法在DataView:上设置筛选字符串

private void SetLeadListFilter(string LeadFilterStr)
{
  this.LeadDataView.RowFilter = filterString;
}

它工作得很好,我可以看到DataGrid显示了正确的过滤DataRow。

但我想给一些UI体验,添加一个繁忙的指示器。所以我把上面的代码放入一个线程:

this.IsBusy = true;
Thread filterDataThread= new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.IsBusy = false;
}));
filterDataThread.Start();

现在很奇怪,我可以看到代码被运行,过滤器被设置。但是DataGrid并没有过滤掉这些行!

所以现在我修改了这个方法,再次将DataView重新分配到CollectionView中:

this.IsBusy = true;
Thread filterDataThread= new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.LeadsCollectionView = CollectionViewSource.GetDefaultView(this.LeadDataView); //Added this
    this.IsBusy = false;
}));
filterDataThread.Start();

现在它工作了!数据正在DataGrid上正确筛选!

那么,当我使用线程时,为什么会发生这种情况呢?这是在线程中使用DataFilter的正确方法吗?

我在带线程的DataView上正确使用了RowFilter吗

不能肯定,但据我所知,您使用

CollectionViewSource.GetDefaultView(this.LeadDataView);

以获取DataGrid的数据源。答案是基于这个假设
所以,如果你要在filterDataThread之外调用这个方法,就像这样:

this.IsBusy = true;
Thread filterDataThread= new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.IsBusy = false;
}));
filterDataThread.Start();
this.LeadsCollectionView =  
  CollectionViewSource.GetDefaultView(this.LeadDataView);

那么带有GetDefaultView的代码可能会在线程工作之前运行——MainThreadfilterDataThread之间会有竞争,MainThread获胜,而DataGrid不会过滤数据。

但如果你要使用你提供的代码:

this.IsBusy = true;
Thread filterDataThread = new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.LeadsCollectionView =  
      CollectionViewSource.GetDefaultView(this.LeadDataView); //Added this
    this.IsBusy = false;
}));
filterDataThread.Start();

过滤将及时开始
所以答案是:
是的,你做的过滤是正确的。但在后台线程中执行操作时,您应该添加代码来处理错误,这样您的应用程序就不会永远是Busy

此外,您应该检查对filterString的安全访问——如果您要启动两个或多个线程进行筛选,则会出现另一场结果不可预测的竞争。