【问题标题】:Async/Await single thread/some threads异步/等待单线程/一些线程
【发布时间】:2018-10-01 03:29:08
【问题描述】:

我需要一些关于正确使用 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() 运行得更快。

【问题讨论】:

  • 你的问题到底是什么?
  • 已更新........
  • 您是否正在寻找类似“如果一个依赖于另一个,则仅按顺序等待任务”之类的东西?目前还不清楚问题是什么。
  • juharr - 这似乎是一个很好的解释。请将其移至答案中
  • 您要求什么“经验法则”? Task 是如果你 await 可能会产生结果的东西。在那之前,它只是一个什么都不做的对象。在您的 NonParallel 方法中,您甚至没有第二个任务,直到第一个任务完成,所以这些方法当然是完全不同的。

标签: c# multithreading asynchronous c#-7.2


【解决方案1】:

在不使用await 的情况下调用GetTaskAsync 时,实际上会得到一个包含要执行的方法(即GetTaskAsync)的Task。但是当调用await GetTaskAsync 时,执行会暂停,直到方法执行完毕,然后你就得到了结果。

让我更清楚:

var task = GetTaskAsync(2000);

这里,任务的类型是Task&lt;string&gt;

var result = await GetTaskAsync(2000);

这里的结果是string

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

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

现在让我们分解一下:

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

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

这是由于内联等待的任务。

但是在Parallel()...

这些任务现在并行运行。这是因为所有 [任务] 在随后等待所有[任务]之前启动,再次,因为 他们回来很热。

关于“热门”任务

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

任务状态部分在这里有助于理解冷任务和热任务的概念:

由公共 Task 构造函数创建的任务被称为冷任务,因为它们的生命周期以非计划的 Created 状态开始,并且仅在对这些实例调用 Start 时才被计划。

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

我邀请您广泛阅读有关async/awaitTasks 的信息。除了我上面提供的资源之外,还有一些资源:

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

Async/Await - Best Practices in Asynchronous Programming

Async and Await

【讨论】:

  • 不错的文章已链接。
猜你喜欢
  • 2020-07-08
  • 2013-02-15
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
相关资源
最近更新 更多