C#在任务中更新UI

Var*_*ain 2 c# wpf multithreading

我是新手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();
                                })); 

    });
}
Run Code Online (Sandbox Code Playgroud)

我不确定这段代码是否正确.我认为无论如何都会出现死锁?

你能指出我如何从Task更新UI?我没有使用async/await 因为UpdateSales是来自第三方库的事件处理程序.

slu*_*ter 7

如您所知,Task.Run将在线程线程上执行.

然后,您可以使用将在该任务完成时运行的ContinueWith - 如果您选择允许您指定TaskScheduler的其中一个覆盖,那么您可以使用TaskScheduler.FromCurrentSynchronizationContext(),它将使用您输入的同步上下文方法on - 如果这是一个UI线程(例如,您在UI事件的事件处理程序中),则同步上下文将是UI线程的同步上下文.

所以你的代码看起来像这样:

Task.Run(() => {
                   ...code to create collection etc...
               }
        )
        .ContinueWith(() => {
                                saleDataGrid.ItemsSource = currentCollection;
                            }
                      , TaskScheduler.FromCurrentSynchronizationContext()
                     );
Run Code Online (Sandbox Code Playgroud)


Ste*_*ary 7

假设UpdateSales在UI线程上调用了一个更清晰的解决方案:

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();
}
Run Code Online (Sandbox Code Playgroud)

正如我在博客中描述的那样,await将在捕获的上下文(在本例中为UI上下文)中自动恢复.我更喜欢使用隐式上下文await而不是Dispatcher直接上下文:代码更短,更便携.