0

I'm just learning about task, and async/await implementation and I'm struggling with a simple code example so I was hoping someone could share some lights as to what is going on.

here's the code:

public async Task<string> DoStuff()
{
    Console.WriteLine("Long running op started");
    var myString = await Task<string>.Run(() =>
    {
        var result = "Test";
        for (int counter = 0; counter < 5000; counter++)
        {
            Console.WriteLine(counter);
        }
        return (result);
    });
    Console.WriteLine(myString);
    return myString;
}

private void button1_Click(object sender, EventArgs e)
{
    DoStuff();

    while (true) {
        Console.WriteLine("Doing Stuff on the Main Thread...................");
        System.Threading.Thread.Sleep(100);
}

So the result of the execution is like this: Long running op started 0 1 2 .... 225 226 Doing Stuff on the Main Thread................... 227 .... etc...

However the code in the DoStuff method that is located after the Task.Run is never reached. And I don't understand why. Of course if I put an await in front of the DoStuff call it works but then the main thread is stuck waiting for execution. This is all for learning purpose only. Thanks

EDIT: as the comments below are saying, it is effectively working when the code is a Main entry program and it was originally in a button click event, this is where the problem occurs actually sorry about the confusion.

9
  • 3
    I just ran your example and "Test" is printed. Are you sure this is the code you're running? Commented Jun 16, 2015 at 8:17
  • 2
    I ran it, and it worked fine; "Test" is printed - are you sure you just didn't blink and miss it in all the other console output? Commented Jun 16, 2015 at 8:18
  • 1
    Confirming, that "Test" is really returned Commented Jun 16, 2015 at 8:19
  • Also, Of course if I put an await in front of the DoStuff call it works but then the main thread is stuck waiting for execution. is misleading - Main will simply return, and the application will end immediately on reaching the await. It sounds like you're not actually running a console application, unlike what the code sample you posted suggests... Commented Jun 16, 2015 at 8:22
  • 1
    @Luaan He can't actually await in Main anyway. I think he got confused. Commented Jun 16, 2015 at 8:22

2 Answers 2

2

The problem is that you're consuming the only available UI thread in your button1_Click(). Presumably, your UI is also frozen indefinitely.

When you use async/await, then execution of the continuation - in your case, the line Console.WriteLine(myString); - will continue in the same synchronization context as the original function was invoked in.

In the case of a console application, the synchronization context is the TPL (Task Parallel Library) thread pool. It has multiple worker threads, so it will use one of them to execute the continuation.

In your GUI application case (WinForms/WPF), the synchronization context is the UI thread. There can be only one UI thread, so when you're occupying that thread with your while(true) loop, nothing else can run - not your continuation, and not other window message, which is why your UI is frozen.

To test this, you can remove the while(true) loop, and see that your UI becomes responsive again, and the continuation will run as expected.

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

1 Comment

Perfect answer thanks a lot, I didn't know about the importance of the synchronization context.
0

When you use a timer for tests you become highly dependent on the characteristics and load of the test system.

Try this instead:

static async Task<string> DoStuff()
{
    Console.WriteLine("Long running op started");
    var myString = await Task.Run(() =>
    {
        var result = "Test";
        for (int counter = 0; counter < 5000; counter++)
        {
            Console.WriteLine(counter);
        }
        return (result);
    });
    Console.WriteLine(myString);
    return myString;
}

static void Main(params string[] args)
{
    var task = DoStuff();

    while (!task.IsCompleted)
    {
        Console.WriteLine("Doing Stuff on the Main Thread...................");
    }
}

1 Comment

this code is much better and makes more sense however I still don't know why mine is not working as it should (if you want to review it please see my last comment above)

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.