当前位置: 首页 > 知识库问答 >
问题:

使用async/await是否会创建新线程?

齐凯康
2023-03-14

我是TPL的新手,我想知道:C#5.0新增的异步编程支持(通过新的异步和等待关键字)与线程的创建有什么关系?

具体来说,每次使用异步/等待是否都会创建一个新线程?如果有许多嵌套方法使用异步/等待,那么是否为这些方法中的每一个都创建了一个新线程?

共有3个答案

尹臻
2023-03-14

抱歉来晚了。

我是TPL的新手,我想知道:对C#5.0来说是新的异步编程支持(通过新的异步和等待关键字)与线程的创建有何关系?

异步/等待不是为创建线程而引入的,而是为了最佳地利用当前线程。

你的应用程序可能会读取文件,等待另一台服务器的响应,甚至使用高内存访问进行计算(只需执行任何IO任务)。这些任务不是CPU密集型的(任何不会100%使用线程的任务)。

考虑一下处理1000个非CPU密集型任务的情况。在这种情况下,创建1000个OS级线程的过程可能会比在单个线程上实际工作消耗更多的CPU和内存(Windows中每个线程4mb,4mb*1000=4GB)。同时,如果按顺序运行所有任务,则可能需要等待IO任务完成。最终需要很长时间才能完成任务,同时保持CPU空闲。

由于我们需要并行性来快速完成多个任务,同时所有并行任务都不需要CPU,但创建线程效率很低。

编译器将在对async方法的任何方法调用时中断执行(使用wait调用)并立即在当前代码分支之外执行代码,一旦到达wait,执行将进入之前的async。这将一次又一次地重复,直到所有异步调用都完成并且满足它们的等待者

如果任何异步方法在没有调用异步方法的情况下具有较重的CPU负载,那么是的,您的系统将变得无响应,并且在当前任务完成之前不会调用所有剩余的异步方法。

陶博涉
2023-03-14

根据MSDN:async关键字

异步方法同步运行,直到到达其第一个等待表达式,此时该方法将挂起,直到等待的任务完成。同时,控件返回给方法的调用方,如下一节中的示例所示。

下面是检查它的示例代码:

class Program

{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    private void Print(string txt)
    {
        string dateStr = DateTime.Now.ToString("HH:mm:ss.fff");
        Console.WriteLine($"{dateStr} Thread #{Thread.CurrentThread.ManagedThreadId}\t{txt}");
    }

    private void Run()
    {
        Print("Program Start");
        Experiment().Wait();
        Print("Program End. Press any key to quit");
        Console.Read();
    }

    private async Task Experiment()
    {
        Print("Experiment code is synchronous before await");
        await Task.Delay(500);
        Print("Experiment code is asynchronous after first await");
    }
}

在另一个线程上执行wait之后,我们看到了experience()方法的代码。

但如果我更换任务。由我自己的代码延迟(方法SomethingElse):

   class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    private void Print(string txt)
    {
        string dateStr = DateTime.Now.ToString("HH:mm:ss.fff");
        Console.WriteLine($"{dateStr} Thread #{Thread.CurrentThread.ManagedThreadId}\t{txt}");
    }

    private void Run()
    {
        Print("Program Start");
        Experiment().Wait();
        Print("Program End. Press any key to quit");
        Console.Read();
    }

    private async Task Experiment()
    {
        Print("Experiment code is synchronous before await");
        await SomethingElse();
        Print("Experiment code is asynchronous after first await");
    }

    private Task SomethingElse()
    {
        Print("Experiment code is asynchronous after first await");
        Thread.Sleep(500);
        return (Task.CompletedTask);
    }
}

我注意到线程保持不变!

总之,我要说异步/等待代码可以使用另一个线程,但前提是该线程是由另一个代码创建的,而不是由异步/等待创建的。

在这种情况下,我认为任务。延迟创建了线程,所以我可以得出结论async/wait不会像@Adriaan Stander所说的那样创建一个新线程。

谢旭
2023-03-14

总之没有

使用异步和等待的异步编程:线程

 类似资料:
  • Async/await 是以更舒适的方式使用 promise 的一种特殊语法,同时它也非常易于理解和使用。 Async function 让我们以 async 这个关键字开始。它可以被放置在一个函数前面,如下所示: async function f() { return 1; } 在函数前面的 “async” 这个单词表达了一个简单的事情:即这个函数总是返回一个 promise。其他值将自动被

  • 在第一章节,我们简要介绍了async/.await,并用它来构建一个简单的服务器。本章将更为详细讨论async/.await的它如何工作以及如何async代码与传统的 Rust 程序不同。 async/.await是 Rust 语法的特殊部分,它使得可以 yield 对当前线程的控制而不是阻塞,从而允许在等待操作完成时,其他代码可以运行。 async有两种主要的使用方式:async fn和asyn

  • 用asyncio提供的@asyncio.coroutine可以把一个generator标记为coroutine类型,然后在coroutine内部用yield from调用另一个coroutine实现异步操作。 为了简化并更好地标识异步IO,从Python 3.5开始引入了新的语法async和await,可以让coroutine的代码更简洁易读。 请注意,async和await是针对coroutin

  • 它与这个问题有着松散的联系:std::thread是否在C11中合并?。虽然问题不同,但意图是一样的: 问题1:使用自己的(或第三方库)线程池来避免昂贵的线程创建是否仍然有意义? 另一个问题的结论是,您不能依赖进行池化(可能是,也可能不是)。然而,std::async(launch::async)似乎有更高的机会被合并。 它不认为这是标准强制的,但我认为,如果线程创建缓慢,所有好的C 11实现都会

  • 想象一下一个按下按钮就能被喜欢的帖子。这个按钮修改了一个远程数据库,所以需要一点时间来将like与特定的帖子相关联。 不喜欢 做了<-------不喜欢做 做完<--------喜欢做完

  • 我有一个安装了ReactJS的NetCore2应用程序。 null VS代码抛出一个错误,告诉我异步只适用于。ts文件。另外,如果我在任何其他函数中使用await,我将得到一个错误,比如。 据我所知,async/await不仅仅是TS...(或者我错了?)。 谢了!