C#在任务中更新UI
我是C#
Task
和线程的新手。
我有一个如下代码: –
public void UpdateSales(object sender, EventArgs args) { Task.Run(() => { // Some code Create Collection ... // Some code with business logic .. // Below code is to update UI // is it safe to update UI like below saleDataGrid.Dispatcher.Invoke((Action) (() => { saleDataGrid.ItemsSource = currentCollection; saleDataGrid.Items.Refresh(); })); }); }
我不确定这段代码是否正确。 我认为无论如何都会出现死锁?
你能指出我如何从Task更新UI? 我没有使用async/await
因为UpdateSales
是来自第三方库的事件处理程序。
假设在UI线程上调用了UpdateSales
,那么更简洁的解决方案就是:
public async void UpdateSales() { var collection = await Task.Run(() => { // Some code Create Collection ... // Some code with business logic .. return currentCollection; }); saleDataGrid.ItemsSource = collection; saleDataGrid.Items.Refresh(); }
正如我在博客中所描述的那样, await
将自动恢复捕获的上下文 (在本例中为UI上下文)。 我更喜欢直接使用await
的隐式上下文而不是Dispatcher
:代码更短,更便携。
如您所知, Task.Run将在线程池线程上执行。
然后,您可以使用将在该任务完成时运行的ContinueWith – 如果您选择允许您指定TaskScheduler的其中一个覆盖 ,那么您可以使用TaskScheduler.FromCurrentSynchronizationContext() ,它将使用您输入的同步上下文方法on – 如果这是一个UI线程(例如,您在UI事件的事件处理程序中),则同步上下文将是UI线程的同步上下文。
所以你的代码看起来像这样:
Task.Run(() => { ...code to create collection etc... } ) .ContinueWith(() => { saleDataGrid.ItemsSource = currentCollection; } , TaskScheduler.FromCurrentSynchronizationContext() );