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线程。我已编辑了此有问题的方法签名,以正确获取它。