What's the right pattern for creating asyncronous services?
Here's what I'm trying to do:
public class EmployeeService
{
public void GetEmployeesAsyc(Action<IEnumerable<Employees>> callback)
{
ThreadPool.QueueUserWorkItem(x => {
var employees = //...fetch employees ...//
callback(employees);
});
}
}
public class ViewModel
{
private EmployeeService _employeeService;
private bool _isLoaded;
public ViewModel()
{
_employeeService = new EmployeeService();
EmployeeList = new ObservableCollection<Employee>();
}
public ObservableCollection<Employee> EmployeeList { get; set; }
public void LoadData()
{
if(_isLoaded) return;
_employeeService.GetEmployeesAsync(employees =>
{
EmployeeList.Clear();
employees.ForEach(employee => EmployeeList.Add(employee));
});
_isLoaded = true;
}
}
public partial class View : PhoneApplicationPage
{
private ViewModel _vm;
public View()
{
InitializeComponent();
_vm = new ViewModel();
this.Loaded += (sender, e) => _vm.LoadData();
}
}
The problem here is that this throws a cross-thread exception:
_employeeService.GetEmployeesAsync(employees =>
{
EmployeeList.Clear();
employees.ForEach(employee => EmployeeList.Add(employee));
});
I can fix it by wrapping it like this:
_employeeService.GetEmployeesAsync(employees =>
{
Dispatcher.BeginInvoke(() =>
{
EmployeeList.Clear();开发者_开发问答
employees.ForEach(employee => EmployeeList.Add(employee));
});
});
but I'm not sure if that's the right way to go about it. Any suggestions?
Nothing wrong with using the dispatcher to get your UI changes from your background thread onto the UI thread. This is one of it's primary purposes.
Some framework elements have this built in for you (such as webclient vs httpwebrequest) to save you the trouble of writing dispatcher code, but using this can lead to UI performance degradation if you're doing a heavy amount of work because you have more code than you need executing on the UI thread. Apps running on devices with constrained resources such as WP7 are particularly sensitive to this.
精彩评论