简体   繁体   中英

How to call an async method, and update the UI from there?

Recently I've finished designing a PagedDataGridView custom control, it works very well, but now I'd like to improve its performance.

How?, well, I've seen some UI blocking when showing new pages.
In short words, this:

public class PagedDataGridView() : UserControl
{
    Paging paging = new Paging();

    public PagedDataGridView()
    {
        paging.LoadDataClientMethod = LoadDataOnGrid;
    }

    private void LoadDataOnGrid()
    {
        // Some heavy set data source here, using functions from 'paging' object
    }
}


What I'm trying to do (using the async / await pattern): That async method DoPaging pauses until the await 'LoadDataOnGrid' is complete, that way the UI thread is not blocked, be asynchronous.

// Class that handles paging methods, variables,
// also offers navigation controls, such as buttons, labels, etc.
internal class Paging
{
    // Represents the method that code client uses to load its own data
    public Action LoadDataClientMethod;

    // HERE: 
    private async Task DoPaging()
    {
        // some calculations

        if (LoadDataClientMethod != null)
        {
            // I realizad that calling Run method, runs it out of context
            // How to run this method, and update the UI
            await Task.Run(() => LoadDataClientMethod());
        }

        // Update controls, showing current page, etc
        UpdateUI();
    }

    // Navigation buttons
    private void btnGoNextPage(object sender, EventArgs e)
    {
        // go next page calculations

        // Then how to call the async method
        DoPaging(); // -> doing this, VS shows a warning:
        /* Because this call is not awaited, the current method
           continues to run before the call is completed */
    }
}

I'm just starting to learn about async - await coding, any correction or advice will be greatly appreciated, thanks.

Just add async to the button click event handler method and await the call to DoPaging() :

private async void btnGoNextPage(object sender, EventArgs e)
{
    await DoPaging();
}

The difference between doing it like this rather than the way you had that gives the warning (and is in fact why the warning is given) is that if you added any code after the call to DoPaging() in the event handler it would now occur after the task has complete, whereas before it would execute immediately after the call.

There is a big difference between:

private void btnGoNextPage(object sender, EventArgs e)
{
    DoPaging();
}

and

private async void btnGoNextPage(object sender, EventArgs e)
{
    await DoPaging();
}

Exception handling . If the former throws an exception, two things might happen:

  1. If you're using .NET 4.0, the swallowed task will be re-thrown from the Finalizer thread and will cause your application to crash
  2. If you're using .NET 4.5, the task will be swallowed and will go un-noticed and will not be re-thrown at all, thus possibly entering your application in a corrupted state which you wont be aware of.

in the latter example, the exception will propogate to the await point, and you can handle it gracefully by adding a try-catch block.

As a side note, i asked you in the comments what kind of work is being done that is blocking your UI thread, and you said that you are making a call to your database to retrieve data. Work being done against a database is IO bound work, and most providers expose async endpoints to access data, such as Entity Framework, ADO.NET, etc. You can make use of that naturally async behavior by not using any threadpool threads to do the work for you (with Task.Run as you're doing in your example). You can do that when you go "async all the way" , and your database query can be used with the await keyword. That way, while the query is retrieving the data, the thread that invoked the query (in your example, the UI thread) is freed and can do more work, thus your UI will stay responsive.

I suggest you look into that and see if your database provider has those async endpoints.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM