c# - 我是否在带线程的 DataView 上正确使用了 RowFilter?

标签 c# wpf multithreading dataview

编辑:我正在使用 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 绑定(bind)到 this.LeadsCollectionView

用户在View中输入过滤文本后,ViewModel会执行该方法在DataView上设置过滤字符串:

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

它工作正常,我可以看到 DataGrid 显示正确过滤的 DataRow。

但是后来我想给一些UI体验,加一个繁忙的指示器。 所以我把上面的代码放到了一个Thread中:

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 的正确方法吗?

最佳答案

不能肯定地说,但据我了解,您使用

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 的代码可能会在您的 Thread 工作之前运行 - 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();

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

此外,您应该检查对 filterString 的安全访问 - 如果您将启动两个或多个线程进行过滤,将会出现另一场具有不可预测结果的竞争。

关于c# - 我是否在带线程的 DataView 上正确使用了 RowFilter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9551040/

相关文章:

c++ - C++ 标准中错误使用 std::memory_order::relaxed 的示例 [n4713 中的 algorithms.parallel.exec/5]

multithreading - 并发不是并行吗?

c# - 线程 : BeginInvoke howto add a complete ListviewItem?

c# - 简单的 MVVM 工具包 - 切换时丢失 ViewModel

java - 将整个 Java 项目移植到 C#

c# - C# 中可见性的系统类型

wpf - Prism/mvvm : binding Columns to DataGrid

wpf - 通过服务保存时如何保持模型一致?

c# - Unregister(this) 从所有内容中取消注册此实例?

c# - 是什么导致mysql中的kill查询