4

I am new to C# Task and threading.

I have a code like below:-

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();
                                })); 

    });
}

I am not sure if this code is correct or not. I am think in any case deadlock can occur?

Can you please point how can i update UI from Task? i am not using async/await because UpdateSales is event handler from third party library.

1
  • 3
    Usually you just call the Dispatcher and check if you need to invoke on it's specific thread. But I'm pretty sure your code won't cause a deadlock Commented Aug 8, 2016 at 13:08

2 Answers 2

13

Assuming that UpdateSales is called on the UI thread, a cleaner solution would be this:

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();
}

As I describe on my blog, the await will automatically resume on a captured context (in this case, the UI context). I much prefer using the implicit context of await rather than Dispatcher directly: the code is shorter and more portable.

Sign up to request clarification or add additional context in comments.

1 Comment

UpdateSales event is getting fire from COM object event handler. Not sure if that will be UI thread. I have edited this method signature in question to get it correctly.
12

As you know, Task.Run will execute on a threadpool thread.

You can then use a ContinueWith which will run at the completion of that task - and if you choose one of the overrides that allows you to specify a TaskScheduler then you can use TaskScheduler.FromCurrentSynchronizationContext() which will use the synchronization context that you entered the method on - if that is a UI thread (for example you are in an event handler for a UI event) then the synchronization context will be that of the UI thread.

So your code will look something like this:

Task.Run(() => {
    //...code to create collection etc...
}).ContinueWith(() => {
    saleDataGrid.ItemsSource = currentCollection;
}).TaskScheduler.FromCurrentSynchronizationContext());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.