简体   繁体   中英

Async/Await single thread/some threads

I need a little rule about correct usage of await. Run this code in .net core c# 7.2:

static class Program
{
    static async Task<string> GetTaskAsync(int timeout)
    {
        Console.WriteLine("Task Thread: " + Thread.CurrentThread.ManagedThreadId);
        await Task.Delay(timeout);
        return timeout.ToString();
    }

    static async Task Main()
    {
        Console.WriteLine("Main Thread: " + Thread.CurrentThread.ManagedThreadId);

        Console.WriteLine("Should be greater than 5000");
        await Watch(NotParallel);
        Console.WriteLine("Should be less than 5000");
        await Watch(Parallel);
    }

    public static async Task Parallel()
    {
        var res1 = GetTaskAsync(2000);
        var res2 = GetTaskAsync(3000);

        Console.WriteLine("result: " + await res1 + await res2);
    }

    public static async Task NotParallel()
    {
        var res1 = await GetTaskAsync(2000);
        var res2 = await GetTaskAsync(3000);

        Console.WriteLine("result: " + res1 + res2);
    }

    private static async Task Watch(Func<Task> func) {
        var sw = new Stopwatch();
        sw.Start();

        await func?.Invoke();

        sw.Stop();
        Console.WriteLine("Elapsed: " + sw.ElapsedMilliseconds);
        Console.WriteLine("---------------");
    }
}

As you all can see the behavior of two methods are different. It's easy to get wrong in practice. So i need a "thumb rule".

Update for real men Please, run code. And explain please why Parallel() runs faster than NonParallel().

结果,女士们。

While calling GetTaskAsync without await , you actually get a Task with the method to execute (that is, GetTaskAsync ) wrapped in. But when calling await GetTaskAsync , execution is suspended until the method is done executing, and then you get the result.

Let me be more clear:

var task = GetTaskAsync(2000);

Here, task is of type Task<string> .

var result = await GetTaskAsync(2000);

Here result is of type string .

So to address your first interrogation: when to await your Tasks really depends on your execution flow.

Now, as to why Parallel() is faster, I suggest your read this article (everything is of interest, but for your specific example, you may jump to Tasks return "hot" ).

Now let's break it down:

The await keyword serves to halt the code until the task is completed, but doesn't actually start it.

In your example, NotParallel() will take longer because your Tasks execute sequentially, one after the other. As the article explains:

This is due to the tasks being awaited inline.

In Parallel() however...

the tasks now run in parallel. This is due to the fact that all [tasks] are started before all [tasks] are subsequently awaited, again, because they return hot.

About 'hot' tasks

I suggest your read the following: Task-based Asynchronous Pattern (TAP)

The Task Status section is of interest here to understand the concepts of cold and hot tasks:

Tasks that are created by the public Task constructors are referred to as cold tasks, because they begin their life cycle in the non-scheduled Created state and are scheduled only when Start is called on these instances.

All other tasks begin their life cycle in a hot state, which means that the asynchronous operations they represent have already been initiated

I invite you to read extensively about async/await and Tasks . Here are a few resources in addition to the ones I provided above:

Asynchronous Programming in C# 5.0 part two: Whence await?

Async/Await - Best Practices in Asynchronous Programming

Async and Await

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