簡體   English   中英

執行返回ObservableCollection的異步搜索

[英]Perform async search that returns ObservableCollection

我正在使用Visual Studio 2015和Entity Framework 6來構建MVVM Light WPF應用程序。 當用戶單擊“搜索”按鈕時,它會調用“ RelayCommand ,該命令已在“視圖模型”的構造函數中定義如下:

SearchEmployeesRelayCommand = new RelayCommand(SearchEmployees);

視圖模型中的SearchEmployees方法如下所示:

private BackgroundWorker _worker;

public void SearchEmployees()
{
    _worker = new BackgroundWorker(); // use this to show busy indicator

    var dataService = new EmployeeDataService();
    _worker.DoWork += (o, ea) =>
    {
        SearchResults = dataService.SearchEmployees(SelectedColumn, SearchValue);
    };
    _worker.RunWorkerCompleted += (o, ea) =>
    {
        IsSearching = false;
    };

    IsSearching = true;
    _worker.RunWorkerAsync();
}

數據服務的搜索方法如下:

public ObservableCollection<EmployeeViewModel> 
    SearchEmployees(string selectedColumn, string searchValue)
{
    var paramEmployee = Expression.Parameter(typeof(Employee), "e");

    var comparison = Expression.Lambda<Func<Employee, bool>>(
        Expression.Equal(
            Expression.Property(paramEmployee, selectedColumn),
            Expression.Constant(searchValue)),
            paramEmployee).Compile();

    using (var context = new MyEntities())
    {
        var query = (from e in context.Employees
                     .Where(comparison)
                     select new EmployeeViewModel
                     {
                         // Various EF model properties...
                     });
        return new ObservableCollection<EmployeeViewModel>(query);
    }
}

如果我嘗試使上述方法asyncawaitable ,如下所示:

return await new ObservableCollection<EmployeeViewModel>(query);

它給出了這個錯誤:

'ObservableCollection'不包含'GetAwaiter'的定義,並且找不到擴展方法'GetAwaiter'接受類型為'ObservableCollection'的第一個參數(您是否缺少using指令或程序集引用?)

如果返回了ObservableCollection如何使搜索async 謝謝。

更新 :為了使繁忙的指示器正常工作,我必須進行以下更改:

_worker.DoWork += async (o, ea) =>
{
    SearchResults = await dataService
        .SearchEmployees(selectedColumnValue, SearchValue);
    IsSearching = false;
};

然后,我完全刪除了_worker.RunWorkerCompleted塊。 可能有更好的方法來做到這一點,但這就是我如何使其工作的方式。

有兩種方法。 首先,您可以保持數據庫訪問同步,並僅在后台線程上運行它。 請注意, Task.RunBackgroundWorker的現代替代品(我有一個博客系列在兩者之間進行了比較 ):

public async Task SearchEmployeesAsync()
{
  var dataService = new EmployeeDataService();
  var selectedColumn = SelectedColumn;
  var searchValue = searchValue;

  IsSearching = true;
  try
  {
    SearchResults = await Task.Run(() => dataService.SearchEmployees(selectedColumn, searchValue));
  }
  finally
  {
    IsSearching = false;
  }
}

另外,由於使用的是EF6,因此可以使數據庫查詢異步,並且完全不會與后台線程發生沖突:

public async Task<ObservableCollection<EmployeeViewModel>> 
    SearchEmployeesAsync(string selectedColumn, string searchValue)
{
  var paramEmployee = Expression.Parameter(typeof(Employee), "e");
  var comparison = Expression.Lambda<Func<Employee, bool>>(
    Expression.Equal(
      Expression.Property(paramEmployee, selectedColumn),
      Expression.Constant(searchValue)),
      paramEmployee).Compile();

  using (var context = new MyEntities())
  {
    var query = (from e in context.Employees
                 .Where(comparison)
                 select new EmployeeViewModel
                 {
                     // Various EF model properties...
                 });
    var data = await query.ToListAsync();
    return new ObservableCollection<EmployeeViewModel>(data);
  }
}

public async Task SearchEmployeesAsync()
{
  var dataService = new EmployeeDataService();
  IsSearching = true;
  try
  {
    SearchResults = await dataService.SearchEmployeesAsync(SelectedColumn, SearchValue);
  }
  finally
  {
    IsSearching = false;
  }
}

應該讓BackgroundWorker.DoWork異步的; 這將導致它“提早結束”並阻止其正常處理異常。 BGW並非旨在與async代碼一起使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM