7

I'm fairly new to async/await programming and sometimes I feel that I understand it, and then all of a sudden something happens and throws me for a loop.

I'm trying this out in a test winforms app and here is one version of a snippet that I have. Doing it this way will block the UI

private async void button1_Click(object sender, EventArgs e)
{

    int d = await DoStuffAsync(c);

    Console.WriteLine(d);

}

private async Task<int> DoStuffAsync(CancellationTokenSource c)
{

        int ret = 0;

        // I wanted to simulator a long running process this way
        // instead of doing Task.Delay

        for (int i = 0; i < 500000000; i++)
        {



            ret += i;
            if (i % 100000 == 0)
                Console.WriteLine(i); 

            if (c.IsCancellationRequested)
            {
                return ret;
            }
        }
        return ret;
}

Now, when I make a slight change by wrapping the body of "DoStuffAsync()" in a Task.Run it works perfectly fine

private async Task<int> DoStuffAsync(CancellationTokenSource c)
    {
        var t = await Task.Run<int>(() =>
        {
            int ret = 0;
            for (int i = 0; i < 500000000; i++)
            {



                ret += i;
                if (i % 100000 == 0)
                    Console.WriteLine(i);

                if (c.IsCancellationRequested)
                {
                    return ret;
                }
            }
            return ret;

        });


        return t;
    }

With all that said, what is the proper way to handle this scenario?

2 Answers 2

18

When you write such code:

private async Task<int> DoStuffAsync()
{
    return 0;
}

This way you are doing things synchronously, because you are not using await expression.

Pay attention to the warning:

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Based on the warning suggestion you can correct it this way:

private async Task<int> DoStuffAsync()
{
    return await Task.Run<int>(() =>
    {
        return 0;
    });
}

To learn more about async/await you can take a look at:

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

5 Comments

The second option you put is what I have in the working code. So then that is the proper and correct way to handle this ?
Yes it is. Read the compiler warning.
Just wondering how to code the Cancel button in this case? Thanks.
What does the cancel button suppose to do?
You might want to remove the async directive and use return Task.FromResult(...) if the implementation is synchronous, instead of using Task.Run.
3

You just need to change the DoStuffAsync task little bit, as below.

private async Task<int> DoStuffAsync(CancellationTokenSource c)
{
     return Task<int>.Run(()=> {
            int ret = 0;

            // I wanted to simulator a long running process this way
            // instead of doing Task.Delay

            for (int i = 0; i < 500000000; i++)
            {



                ret += i;
                if (i % 100000 == 0)
                    Console.WriteLine(i);

                if (c.IsCancellationRequested)
                {
                    return ret;
                }
            }
            return ret;
        });
}

1 Comment

👍🏻 from the CancellationTokenSource

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.