异步/等待单线程/一些线程

时间:2018-04-20 12:01:34

标签: c# multithreading asynchronous c#-7.2

我需要一些关于正确使用await的规则。在.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("---------------");
    }
}

大家可以看到两种方法的行为不同。在实践中容易出错。所以我需要一个&#34;拇指规则&#34;。

真人更新请运行代码。并解释为什么Parallel()比NonParallel()运行得更快。

Results, for ladies.

1 个答案:

答案 0 :(得分:3)

在没有GetTaskAsync的情况下调用await时,你实际上得到一个任务,其中包含要执行的方法(即GetTaskAsync)。但是当调用await GetTaskAsync时,执行暂停,直到方法执行完毕,然后你得到结果。

让我更清楚一点:

var task = GetTaskAsync(2000);

此处,任务类型为Task<string>

var result = await GetTaskAsync(2000);

此处的结果是string类型。

因此,要解决您的第一次询问:何时等待您的任务实际上取决于您的执行流程。

现在,为什么Parallel()更快,我建议您阅读此article(一切都很有趣,但对于您的具体示例,您可以跳转到任务返回“热门” )。

现在让我们分解一下:

  

await关键字用于暂停代码,直到任务完成,   但实际上并没有启动它。

在您的示例中,NotParallel()将花费更长的时间,因为您的任务依次执行,一个接一个地执行。正如文章所解释的那样:

  

这是由于正在等待内联任务。

然而在Parallel() ......

  

任务现在并行运行。这是因为所有[任务]   在所有[任务]随后等待之前开始,因为   他们回来了。

关于“热门”任务

我建议您阅读以下内容:Task-based Asynchronous Pattern (TAP)

任务状态部分非常感兴趣,可以了解冷热任务的概念:

  

公共任务构造函数创建的任务称为冷任务,因为它们在非调度的创建状态下开始其生命周期,并且仅在对这些实例调用Start时进行调度。

     

所有其他任务在热状态下开始其生命周期,这意味着它们所代表的异步操作已经启动

我邀请您详细阅读async/awaitTasks。除了上面提供的资源之外,还有一些资源:

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

Async/Await - Best Practices in Asynchronous Programming

Async and Await