c# – asp.net核心和kestrel线程池中的异步处理
我是ASP.NET Core和C#的新手,一般来自
Java世界,我对async / await关键字如何工作有点困惑:
This article解释说如果一个方法标记为异步,则意味着
所以我认为在异步方法和在字节码/虚拟机级别上实现的同一线程上运行的调用者之间传递控制是一种非常酷的方式.我的意思是我期望下面的代码 public static void Main(string[] args) { int delay = 10; var task = doSthAsync(delay); System.Console.WriteLine("main 1: " + Thread.CurrentThread.ManagedThreadId); // some synchronous processing longer than delay: Thread.Sleep(2 * delay) System.Console.WriteLine("main 2: " + Thread.CurrentThread.ManagedThreadId); task.Wait(); } public static async Task<String> doSthAsync(int delay) { System.Console.WriteLine("async 1: " + Thread.CurrentThread.ManagedThreadId); await Task.Delay(delay); System.Console.WriteLine("async 2: " + Thread.CurrentThread.ManagedThreadId); return "done"; } 会写的 async 1: 1 main 1: 1 main 2: 1 async 2: 1 通过使用await关键字将控制从doSthAsync传递给Main,然后使用task.Wait()返回doSthAsync(并且所有这些都发生在单个线程上). 但是上面的代码实际上是打印的 async 1: 1 main 1: 1 async 2: 4 main 2: 1 这意味着它只是一种将“异步”方法委托给单独线程的方法,如果当前线程忙,这几乎与上述文章所述的相反:
因此,由于异步方法的“延续”显然是或者至少可以安排在不同的线程上运行,因此我有一些问题似乎是C#应用程序可伸缩性的基础: 每个异步方法是否可以在新生成的线程上运行,或者C#运行时是否为此目的维护特殊的线程池,在后一种情况下,如何控制此池的大小? 在ASP.NET Core的情况下:如何控制Kestrel用于执行异步实体框架操作或其他(网络)I / O的线程池的大小?它是否与用于接受HTTP请求的线程池相同? 据我所知,如果所有I / O都是异步完成的,那么这些池的大小(无论是实际上只有1个线程池还是2个独立的)都与打开到外部资源的传出连接数没有任何关系像DB,对吗? (运行异步代码的线程将继续接受新的HTTP请求,并且由于它们的处理将打开传出连接(到DB或某些Web服务器以从Web获取某些资源),尽可能快地进行,而不会有任何阻塞) 我也有“只是出于好奇”的问题:为什么实际上没有实现async / await来在同一个线程上执行异步任务?我不知道如何在Windows上实现它,但在Unix上,这可以使用select / poll系统调用或信号来实现,所以我相信有一种方法可以在Windows上实现这一点,它将是一个非常酷的语言功能确实. 谢谢! 解决方法
await使用SynchronizationContext.Current的值来安排延续.在控制台应用程序中,默认情况下没有当前的同步上下文;所以它只是使用线程池线程来安排延续.在具有消息循环的应用程序(例如winforms,WPF或winphone应用程序)中,消息循环将当前同步上下文设置为将所有消息发送到消息循环的上下文,从而在UI线程上运行它们.
在ASP应用程序中,还会有一个当前的同步上下文,但它不是一个特定的线程.相反,当需要为同步上下文运行下一条消息时,它需要一个线程池线程,使用正确请求的请求数据进行设置,然后让它运行该消息.这意味着在ASP应用程序中使用同步上下文时,您知道一次只能运行多个操作,但它不一定是处理每个响应的单个线程. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |