c# - 异步/等待单线程/一些线程

标签 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("---------------");
    }
}

如您所见,两种方法的行为是不同的。实践中很容易出错。所以我需要一个“经验法则”。

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

Results, for ladies.

最佳答案

打电话时 GetTaskAsync没有await ,你实际上得到了一个包含执行方法(即 GetTaskAsync )的任务。但是当调用 await GetTaskAsync 时, 执行暂停,直到方法执行完成,然后你得到结果。

让我说得更清楚:

var task = GetTaskAsync(2000);

在这里,任务的类型是 Task<string> .

var result = await GetTaskAsync(2000);

这里的结果是 string 类型.

因此,为了解决您的第一个问题:何时等待您的任务实际上取决于您的执行流程。

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

现在让我们分解一下:

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

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

This is due to the tasks being awaited inline.

Parallel()然而……

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.

关于“热门”任务

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

任务状态部分在这里很有趣,可以理解冷任务和热任务的概念:

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

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

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

Async/Await - Best Practices in Asynchronous Programming

Async and Await

关于c# - 异步/等待单线程/一些线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49941204/

相关文章:

c# - 从Texture2D获取SharpDX.Direct2D1.Bitmap

ios - 在单个 NSOperationQueue iOS 中管理多个操作,例如暂停/恢复单个操作

java - 结束线程的执行而不使用其 stop() 方法

java - Java 进程产生了数千个线程……为什么?

java - Tyrus Websocket 实现中的异步消息传递是否有序?

c# - 检查两个 URL 是否相同

c# - .NET 随机程序集在磁盘上被修改

javascript - 带有异步请求的 NodeJS

c# - 从 C# 调用 C++ 函数并将数据发送回 C#

c# - 使用拆分器使 ItemsControl 子项可调整大小