1

I am new to Winforms coming from web and I am trying to get my head around asynchronous calls.

I have a dropdown, which I would like to call some methods to update 3 tabs on my page. I would like to do these asynchronously so it doesn't block the UI, and put a 'Loading...' message on each tab and load them all independently of each other, with the user being able to click through each tab still and see the progress of the loading.

I have the following, however this is still locking the UI, can someone point me in the right direction for where I am going wrong?

This is my dropdown event handler

    private async void ddlRoles_SelectedIndexChanged(object sender, EventArgs e)
    {
        await Task.Run(async () =>
        {
            await setTab1();
        });

        await Task.Run(async () =>
        {
            await setTab2();
        });

        await Task.Run(async () =>
        {
            await setTab3();
        });
    }

This is an example of one of my tasks which I would like to run asynchronously.

    private async Task setTab1()
    {
        if (tabl1Panel.InvokeRequired)
        {
            this.Invoke(new MethodInvoker(async delegate ()
            {
                await setTab1();
            }));
            return;
        }

        // LONG RUNNING CODE HERE...
    }
2
  • @x... no, that's not it. Recursion doesn't cause any UI problems. Awaiting a task on the UI thread that itself tries to run code on the already blocked UI thread (with Invoke) is the problem Commented Aug 10, 2016 at 8:17
  • 1
    Don't use Threads, you are unlikely to be doing any CPU intensive work. The word "Loading" implies you are doing I/O, in which case you should be doing asynchronous single thread. Commented Aug 10, 2016 at 8:22

1 Answer 1

2

The Invoke call you are using to run setTab1() means the code runs on the UI thread, hence why the UI locks up.

Try doing as much as possible within setTab1() without using Invoke(), and only use Invoke() to run code to update the UI once you have all the data you need.

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

4 Comments

Ok... so is what you are saying for each tab, do as much of the work as possible in a separate async method without the invoke, then call a separate method to update the UI after that has completed?
@user3284707 that's what every tutorial and guidance says. The simplest example is eg var result=await someHeavyFunc(); updateUi();. If you want to publish regular progress updates use IProgress<T> and the Progress<T> implementation to send messages from a task to the UI
Thanks very much, I will take a look and see if I can make it work :)
This has solved my issue.. thank you for your answer!

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.