简体   繁体   English

异步方法如何使用堆栈?

[英]How do async methods use stack?

I just started to use .NET async programming and everyone tells that it's better for server-side code because if I use async keywork ASP.NET won't create threads for every request and will reuse the same threads for all async code. 我刚刚开始使用.NET异步编程,每个人都说它对服务器端代码更好,因为如果我使用异步keywork,ASP.NET将不会为每个请求创建线程,并将为所有异步代码重用相同的线程。

Because every thread needs stack and there may be hundreds of threads, it allows the opportunity to save huge amount of memory, eg: 因为每个线程都需要堆栈,并且可能有数百个线程,所以它有机会节省大量内存,例如:

regular: 1500 threads x 2mb = 3000 mb
async:   20 threads x 2mb   =   40 mb

But does it mean that async code is executing without stack? 但它是否意味着异步代码在没有堆栈的情况下执行? Or where is it stored and how does .NET use it? 或者它存储在哪里以及.NET如何使用它?

Every thread you create allocates a complete stack, no matter how little of it you use on that thread. 您创建的每个线程都会分配一个完整的堆栈,无论您在该线程上使用多少。
Therefore, creating fewer threads will save memory. 因此,创建更少的线程将节省内存。

When an async method is waiting for an operation to finish, it saves its state in a compiler-generated object (like a closure for lambda expressions) on the GC-managed heap. 当异步方法等待操作完成时,它会将其状态保存在GC管理的堆上的编译器生成的对象(如lambda表达式的闭包)中。

Think about what the stack is for: 想想堆栈的用途:

1) Temporary space needed during the execution of individual statements and expressions. 1)执行个别陈述和表达时所需的临时空间。 When you say "a = b + c + d" then the result of "b + c" has to be stored somewhere before it is added to d. 当你说“a = b + c + d”时,“b + c”的结果必须存储在某个地方才能加到d中。

2) Storage of other variables whose lifetimes are known to be equal to or less than the activation of the current method. 2)存储其寿命已知等于或小于当前方法激活的其他变量。

3) What code to run after the activation of the current method finishes. 3)激活当前方法后要运行的代码。

Async methods use stack only for the first. 异步方法仅对第一个使用堆栈。 (And even then might have to move some of those temporaries onto the heap in some cases.) Since variables of async methods might last longer than the current activation of the method, they have to be moved onto the heap. (在某些情况下,甚至可能必须将其中一些临时值移到堆上。)由于异步方法的变量可能比当前方法的激活持续时间更长,因此必须将它们移动到堆上。 And the whole point of an async method is that it stores its continuation elsewhere , it does not use the stack as the reification of continuation. 异步方法的重点在于它将其延续存储在其他地方 ,它不使用堆栈作为延续的具体化。

Therefore async methods make very little use of the stack. 因此,异步方法很少使用堆栈。 Rather, they use heap memory to store their activation and continuation information. 相反,它们使用堆内存来存储它们的激活和延续信息。

But does it mean that async code is executing without stack? 但它是否意味着异步代码在没有堆栈的情况下执行?

It means that async code is waiting without stack. 这意味着async代码没有堆栈的情况下等待 For example, when you have code like this: 例如,当你有这样的代码时:

Uri url = CreateUrl(id);
string result = await DownloadData(url);
int result = ProcessData(result);

Then CreateUrl() and ProcessData() execute normally on a thread and use that thread's stack. 然后CreateUrl()ProcessData()在一个线程上正常执行并使用该线程的堆栈。 But during the time DownloadData() is waiting for the download to complete, no thread is used (assuming DownloadData() is written correctly asynchronously). 但是在DownloadData()等待下载完成的时候,没有使用任何线程(假设正确地异步写入DownloadData() )。 This is a big advantage for ASP.NET applications (and similar), because it means a thread is blocked only for a short amount of time and a small amount of threads can be used to handle large amount of requests. 这对于ASP.NET应用程序(以及类似的)来说是一个很大的优势,因为它意味着线程仅在很短的时间内被阻塞,并且可以使用少量线程来处理大量请求。

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

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