繁体   English   中英

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

[英]Async/Await single thread/some threads

我需要一个关于正确使用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("---------------");
    }
}

你们都可以看到两种方法的行为是不同的。 在实践中很容易出错。 所以我需要一个“拇指规则”。

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

结果,女士们。

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

让我更清楚一点:

var task = GetTaskAsync(2000);

这里,task的类型为Task<string>

var result = await GetTaskAsync(2000);

这里的结果是string类型。

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

现在,至于为什么Parallel()更快,我建议你阅读这篇文章 (一切都很有趣,但对于你的具体例子,你可以跳转到Tasks返回“热门” )。

现在让我们分解一下:

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

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

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

Parallel()然而......

这些任务现在并行运行。 这是因为所有[任务]在随后等待所有[任务]之前开始,因为它们返回热点。

关于'热'任务

我建议您阅读以下内容: 基于任务的异步模式(TAP)

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

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

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

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

C#5.0中的异步编程第二部分:从哪里等待?

Async / Await - 异步编程的最佳实践

异步和等待

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM