我使用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);
}
}
如果我尝试制作上述方法async
和awaitable
,请执行以下操作:
return await new ObservableCollection<EmployeeViewModel>(query);
它给出了这个错误:
&#39;的ObservableCollection&#39;不包含&#39; GetAwaiter&#39;的定义没有扩展方法&#39; GetAwaiter&#39;接受类型&#39; ObservableCollection&#39;的第一个参数。可以找到(你错过了使用指令或程序集引用吗?)
如果它async
返回ObservableCollection
,您如何进行搜索?感谢。
更新:为了使忙碌指示灯正常工作,我必须进行此更改:
_worker.DoWork += async (o, ea) =>
{
SearchResults = await dataService
.SearchEmployees(selectedColumnValue, SearchValue);
IsSearching = false;
};
我完全删除了_worker.RunWorkerCompleted
块。可能有更好的方法,但这就是我如何运作。
答案 0 :(得分:2)
有几种方法。首先,您可以保持数据库访问同步,并在后台线程上运行它。请注意,Task.Run
是BackgroundWorker
的现代替代品(我有一个blog series that draws parallels between the two):
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
代码。