翻译 异步I/O不会创建新的线程
异步I/O不会创建新的线程
本文翻译自 Stephen Cleary 的 [There is No Thread] 原文地址 https://blog.stephencleary.com/2013/11/there-is-no-thread.html
这是异步编程最基本的事实 : 异步I/O不会创建新的线程
反对这个事实的人很多,他们对此的看法是 "如果我await一个操作,那么一定会有一个线程正在等待,它可能是一个线程池的线程,或者是操作系统线程,或者是某个设备的驱动程序"
不用关注这些看法, 只需要记住如果异步操作是纯粹的(方法全是async),那么就不会产生新的线程
不过这么一个简单的结论显然并不能够让他们信服,下面就看看异步到底发生了什么
让我们跟踪一个异步操作直到硬件层面,注:Net部分和设备驱动部分将被简化描述 (因为细节太多了)
下面是一个通用的写入操作 (例如 文件、网络、USB面包机等等)
private async void Button_Click(object sender, RoutedEventArgs e)
{
byte[] data = ...
await myDevice.WriteAsync(data, 0, data.Length);
}
我们已经知道在await的时候UI线程不会被阻塞,那么问题来了: 是否是UI线程创建了另外一个线程杀了祭天换来了自己的自由....
关于UI线程是否犯下这一恶行,让我们深入推断一下
首先 : 看看类库 (BCL的代码) 假设 WriteAsync 是使用.Net中标准的异步方式平台调用(P/Invoke)I/O系统,这是一个基于异步方式的I/O,所以这会在设备的底层上启动一个win32异步方式I/O操作句柄
然后操作系统会告诉设备驱动程序进行写操作,代码实现是构造出表示写请求的对象,这个对象称为I/O请求包(IRP)
设备驱动程序接收到IRP后会向设备发出一个命令来写出数据,如果这个设备支持直接内存存取技术(DMA),只需将缓冲区地址写入设备寄存器即可,设备驱动程序能做到将IRP标记为 "pending" 后交把控制权交还操作系统

在这里发现了真相的核心所在 : 在处理IRP时,设备驱动是不允许阻塞的。这意味着如果IRP不能立即完成,那么它必须异步处理,即使对于同步的api也是如此!在设备驱动级别,所有(有意义)的请求都是异步的
引用书籍里的知识 "无论是什么类型的I/O请求,应用程序向驱动程序发出的I/O操作都是异步执行的"
在IRP为 "pending" 时,操作系统返回到类库,类库将未完成的任务返回到应用程序的按钮单击事件方法,该方法挂起async方法,UI线程继续执行
我们已经跟踪请求到系统的尽头 直到物理设备
现在写入操作正在飞快的进行中,有多少个线程正在处理它?
答案是没有
没有设备驱动程序线程、操作系统线程、BCL线程或者写在处理写操作的线程池线程(
翻译 异步I/O不会创建新的线程的更多相关文章
- nodejs中使用worker_threads来创建新的线程
目录 简介 worker_threads isMainThread MessageChannel parentPort和MessagePort markAsUntransferable SHARE_E ...
- 【C++】【MFC】创建新的线程函数
DWORD WINAPI MyThreadProc (LPVOID lpParam){ somestruct* pN = (somestruct*)lpParam; // 将参数转为你的类型 ... ...
- 多线程编程之Windows环境下创建新线程
转自: http://www.cnblogs.com/lgxqf/archive/2009/02/10/1387480.html 在 Win32 API 中,创建线程的基本函数是 CreateThre ...
- Spark无法创建新线程
Spark提交程序报错,无法创建新的线程 原因是因为这台公用机器上跑的进程太多了,需要修改Linux参数,允许用户最大进程数 查看允许用户最大进程数配置 ulimit -a 修改允许用户最大进程数配置 ...
- Java多线程-新特性-线程池
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- JVM最多能创建多少个线程:unabletocreatenewnativethread
最近需要测试一个长连接服务器,数据上需要达到100W的长连接,测试的客户端,一个线程保持一个连接,发现linux服务器默认创建到3200多个线程的时候,就会报错这个错误“java.lang.OutOf ...
- Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程
待解决的问题 Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程 解决办法 为spring session添加spr ...
- Linux 循环创建多个线程
这里说一下相关的基础知识: 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本质仍是进程(在Linux环境下) 进程:独立地址空间,拥有PCB 线 ...
- UNIX环境编程学习笔记(26)——多线程编程(一):创建和终止线程
lienhua342014-11-08 在进程控制三部曲中我们学习了进程的创建.终止以及获取终止状态等的进程控制原语.线程的控制与进程的控制有相似之处,在表 1中我们列出了进程和线程相对应的控制原语. ...
随机推荐
- Analysis of Web.xml in Hello1 project
一.web.xml文件介绍 The web.xml file contains several elements that are required for a Facelets applicatio ...
- 土制Excel导入导出及相关问题探讨
转载请注明出处https://www.cnblogs.com/funnyzpc/p/10392085.html 新的一年,又一个开始,不见收获,却见年龄,好一个猪年,待我先来一首里尔克的诗: < ...
- Java学习之软件安装
成功安装了jdk-10.0.1.eclipse-committers-2018-09-win32-x86_64.mysql-5.7.18.1和tomcat-9.0.0.M17
- tf.contrib.slim add_arg_scope
上一篇文章中我们介绍了arg_scope函数,它在每一层嵌套中update当前字典中参数形成新的字典,并入栈.那么这些参数是怎么作用到代码块中的函数的呢?比如说如下情况: with slim.arg_ ...
- FTP连接超时
今天程序在连接FTP服务器,突然无法连接,用Windows 的 Explorer能正常连接,但用 WebRequest.WebResponse连接时,总是抛出连接超时异常. 后查找相关资料,原因是:程 ...
- windows服务定时任务
其实定时任务时不时会碰到,只不过解决方案也不是只有一个,网上也有很多文章,但是没有一篇说得很清楚,尤其是安装环节,今天就着重说一下安装, 其他步骤带过,C#开发windows服务,开发,安装,调试 1 ...
- Linux系统下如何运行.sh文件
在Linux系统下运行.sh文件有两种方法,比如我在root目录下有个datelog.sh文件 第一种(这种办法需要用chmod使得文件具备执行条件(x): chmod u+x datelog.sh) ...
- Winsock编程基继承基础(网络对时程序)
#include <iostream> #include <stdio.h> #include "InitSock.h" using namespace s ...
- Anveshak: Placing Edge Servers In The Wild
Anveshak:在野外放置边缘服务器 本文为SIGCOMM 2018 Workshop (Mobile Edge Communications, MECOMM)论文. 笔者翻译了该论文.由于时间仓促 ...
- Vs 发布编译问题
如果勾选了预编译 发布后的目录会有PrecompiledApp.config文件,bin目录中会有App_global.asax.dll和App_global.asax.compiled文件 不勾选预 ...