Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42642

We need to have "double" await so that GUI will not freeze?

I expect my GUI will not hang, after reading Asynchronous Programming with Async and Await (C# and Visual Basic)

    public async Task<string> DoBusyJob()
    {
        // Busy Job
        Thread.Sleep(10000);
        i++;
        return "Finished " + i;
    }

    int i = 0;

    private async void button1_Click(object sender, EventArgs e)
    {
        // Hang!
        string result = await DoBusyJob();

        this.label1.Text = result;
    }

But, it is not. It still hang. I realize I need to add additional await in DoBusyJob

    public async Task<string> DoBusyJob()
    {
        // Busy Job
        await Thread.Sleep(10000);
        i++;
        return "Finished " + i;
    }

    int i = 0;

    private async void button1_Click(object sender, EventArgs e)
    {
        // OK!
        string result = await DoBusyJob();

        this.label1.Text = result;
    }

May I know why is it so? Do I really need to have double await? What if the following case?

    public async Task<string> DoBusyJob()
    {
        // How to prevent Hang?
        for (int j = 0; j < 10000000; j++) {
            double m = Math.Sqrt(1) + Math.Sqrt(2) + Math.Sqrt(3);
        }
        i++;
        return "Finished " + i;
    }

    int i = 0;

    private async void button1_Click(object sender, EventArgs e)
    {
        // Hang!
        string result = await DoBusyJob();

        this.label1.Text = result;
    }

Upvotes: 3

Views: 1454

Answers (3)

I wish I could understand your // OK! upon adding await to Thread.Sleep(10000);
It is impossible to await on method Sleep() returning void
It is possible to await only on method designating its signature Task or Task<TResult> as return type

Async method is executed synchronously without (or until) await so blocking UI thread
await Task.Run() should return at once to (previous) UI synchronization context, i.e. to continue with next i++; line execution

public async Task<string> DoBusyJob()
{
  // Busy Job

  await Task.Run(() =>
    {
        for (int j = 0; j < 10000000; j++)
        {
            double m = Math.Sqrt(1) + Math.Sqrt(2) + Math.Sqrt(3);
        }
    }
                );
  i++;
  return "Finished " + i;
}

Upvotes: 0

Stephen Cleary
Stephen Cleary

Reputation: 456322

There's a great answer in the async / await FAQ:

Q. Does using the “async” keyword on a method force all invocations of that method to be asynchronous?

A. No. When you invoke a method marked as “async”, it begins running synchronously on the current thread...

Q. Does the “async” keyword cause the invocation of a method to queue to the ThreadPool? To create a new thread? To launch a rocket ship to Mars?

A. No. No. And no...

You may find my async / await intro helpful.

Upvotes: 2

Michael Petito
Michael Petito

Reputation: 13161

Please see the excellent answers to this question in regards to async methods.

Adding async is insufficient to make the execution of your method asynchronous if you are not using await with already asynchronous methods. In that case, you need to return a Task instance that represents the execution of your work, for ex. by calling Task.Factory.StartNew.

Upvotes: 6

Related Questions