C#更新任务中的UI
我不熟悉C#更新任务中的UI,c#,wpf,multithreading,C#,Wpf,Multithreading,我不熟悉C#任务和线程 我有如下代码:- 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
C#
任务
和线程
我有如下代码:-
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();
}));
});
}
我不确定这个代码是否正确。我认为在任何情况下都可能出现僵局
您能指出如何从任务更新UI吗?我没有使用async/await
,因为UpdateSales
是来自第三方库的事件处理程序 如您所知,将在线程池线程上执行
然后,您可以使用将在该任务完成时运行的,如果您选择允许您指定TaskScheduler的,那么您可以使用将使用您在其上输入方法的同步上下文的,如果它是UI线程(例如,您在UI事件的事件处理程序中)然后同步上下文将是UI线程的上下文
因此,您的代码将如下所示:
Task.Run(() => {
...code to create collection etc...
}
)
.ContinueWith(() => {
saleDataGrid.ItemsSource = currentCollection;
}
, TaskScheduler.FromCurrentSynchronizationContext()
);
假设在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();
}
正如我在我的博客中所描述的,用户界面(在本例中是UI上下文)。我更喜欢使用
await
的隐式上下文,而不是直接使用Dispatcher
:代码更短,更便于移植。通常您只需调用Dispatcher并检查是否需要在其特定线程上调用。但我很确定您的代码不会导致死锁UpdateSales
事件从COM对象事件处理程序中触发。不确定这是否是UI线程。我已编辑了此有问题的方法签名,以正确获取它。