.Net中的I/O thread vs. worker thread

本文深入探讨了.NET环境下的I/O线程与工作线程概念,解释了它们之间的区别与联系,并指出Vista之前Win32系统中关于I/O线程与非I/O线程的划分,以及.NET库对原始Overlapped IO的包装与使用。

Stackoverflow.com上的一个post(http://stackoverflow.com/questions/2099947/simple-description-of-worker-and-i-o-threads-in-net)关于它们的解释比较准确,原文摘录如下:

The term 'I/O thread' in.net/CLR refers to the threads the ThreadPool reserves in order to dispatchNativeOverlapped callbacks from"overlapped" win32 calls (also known as "completion portI/O"). The CLR maintains its own I/O completion port, and can bind anyhandle to it (via the ThreadPool.BindHandle API).

There is really no technical difference between 'worker thread' and 'I/O thread' -- they are both justnormal threads. But the CLR ThreadPool keeps separate pools of each simply toavoid a situation where high demand on worker threads exhausts all the threadsavailable to dispatch native I/O callbacks, potentially leading to deadlock.(Imagine an application using all 250 worker threads, where each one is waitingfor some I/O to complete).

 

需要注意的是:Vista之前的Win32中有2个类似的概念:I/O worker thread和non-I/O worker thread,这两个概念是针对Win32thread pool提出来的,它们的定义和区别可以引用MSDN的话:

An I/O worker thread is athread that waits in an alertable wait state. Work items are queued to I/Oworker threads as Asynchronous Procedure Calls (APC).”,“Anon-I/Oworker thread waits on I/O completion ports.”。

 

几点注释:

1.       据MSDN,.Net提供的NativeOverlapped就是Win32提供的OVERLAPPED结构,同时尾部附带一些bytes(不在此追究)。在.Net DllImport时,CLR在native DLL中解析(寻找)函数时,只关心函数的名称,不关心函数的参数情况,即解析过程中不存在C++中的函数overload的概念,亦即函数的signature不考虑参数(这是C的做法)。

2.       .Net库已经把Overlapped IO进行了包装,一般情况下,不需要直接使用这些原始元素来完成我们手头的任务。但是,这个机制在.Net下是存在的并且是可用的。

3.       .Net thread pool中的I/O worker thread似乎刚好就是Win32threadpool中的non-I/O worker thread。Microsoft®不应该制造这样的confusion,所幸的是,Windows® Vista之后的thread pool已经抛弃了这两个概念,转而使用了统一的thread类型。

2025-07-07 09:37:09 [ForkJoinPool.commonPool-worker-1] ERROR i.m.c.t.HttpClientSseClientTransport: SSE connection error java.util.concurrent.CompletionException: java.net.ConnectException at java.base/java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:368) at java.base/java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:377) at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1152) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1773) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: java.net.ConnectException: null at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1047) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:198) at java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:230) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:206) at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) ... 6 common frames omitted Caused by: java.nio.channels.ClosedChannelException: null at java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:195) at java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:760) at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:848) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$0(PlainHttpConnection.java:183) at java.base/java.security.AccessController.doPrivileged(AccessController.java:569) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:185) ... 10 common frames omitted 2025-07-07 09:37:09 [ForkJoinPool.commonPool-worker-1] ERROR reactor.core.publisher.Operators: Operator called default onErrorDropped reactor.core.Exceptions$ErrorCallbackNotImplemented: java.net.ConnectException Caused by: java.net.ConnectException: null at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1047) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:198) at java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:230) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:206) at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1773) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: java.nio.channels.ClosedChannelException: null at java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:195) at java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:760) at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:848) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$0(PlainHttpConnection.java:183) at java.base/java.security.AccessController.doPrivileged(AccessController.java:569) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:185) ... 10 common frames omitted
07-08
Download https://maven.aliyun.com/repository/google/androidx/profileinstaller/profileinstaller/1.3.0/profileinstaller-1.3.0-sources.jar, took 123 ms Warning: Failed to download any source lists! Warning: IO exception while downloading manifest: Warning: IO exception while downloading manifest: java.net.ConnectException: Connection refused: connect java.net.ConnectException: Connection refused: connect at java.base/sun.nio.ch.Net.connect0(Native Method) at java.base/sun.nio.ch.Net.connect0(Native Method) at java.base/sun.nio.ch.Net.connect(Unknown Source) at java.base/sun.nio.ch.Net.connect(Unknown Source) at java.base/sun.nio.ch.Net.connect(Unknown Source) at java.base/sun.nio.ch.Net.connect(Unknown Source) at java.base/sun.nio.ch.NioSocketImpl.connect(Unknown Source) at java.base/sun.nio.ch.NioSocketImpl.connect(Unknown Source) at java.base/java.net.Socket.connect(Unknown Source) at java.base/java.net.Socket.connect(Unknown Source) at java.base/java.net.Socket.connect(Unknown Source) at java.base/sun.net.NetworkClient.doConnect(Unknown Source) at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source) at java.base/java.net.Socket.connect(Unknown Source) at java.base/sun.net.NetworkClient.doConnect(Unknown Source) at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source) at java.base/sun.net.www.http.HttpClient$1.run(Unknown Source) at java.base/sun.net.www.http.HttpClient$1.run(Unknown Source) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at java.base/sun.net.www.http.HttpClient.privilegedOpenServer(Unknown Source) at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source) at java.base/sun.net.www.protocol.https.HttpsClient.<init>(Unknown Source) at java.base/sun.net.www.protocol.https.HttpsClient.New(Unknown Source) at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(Unknown Source) at java.base/sun.net.www.http.HttpClient$1.run(Unknown Source) at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(Unknown Source) at java.base/sun.net.www.http.HttpClient$1.run(Unknown Source) at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source) at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source) at java.base/sun.net.www.http.HttpClient.privilegedOpenServer(Unknown Source) at com.android.sdklib.repository.legacy.remote.internal.DownloadCache.openUrl(DownloadCache.java:254) at java.base/sun.net.www.http.HttpClient.openServer(Unknown Source) at com.android.sdklib.repository.legacy.remote.internal.DownloadCache.downloadAndCache(DownloadCache.java:631) at com.android.sdklib.repository.legacy.remote.internal.DownloadCache.openCachedUrl(DownloadCache.java:462) at java.base/sun.net.www.protocol.https.HttpsClient.<init>(Unknown Source) at java.base/sun.net.www.protocol.https.HttpsClient.New(Unknown Source) at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(Unknown Source) at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(Unknown Source) at com.android.sdklib.repository.legacy.LegacyDownloader.downloadAndStream(LegacyDownloader.java:82) at com.android.repository.impl.downloader.LocalFileAwareDownloader.downloadAndStream(LocalFileAwareDownloader.java:51) at com.android.repository.impl.manager.RemoteRepoLoaderImpl.lambda$fetchPackages$0(RemoteRepoLoaderImpl.java:140) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) at java.base/java.util.concurrent.FutureTask.run(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source) at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source) at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source) at com.android.sdklib.repository.legacy.remote.internal.DownloadCache.openUrl(DownloadCache.java:254) at com.android.sdklib.repository.legacy.remote.internal.DownloadCache.downloadAndCache(DownloadCache.java:631) at com.android.sdklib.repository.legacy.remote.internal.DownloadCache.openCachedUrl(DownloadCache.java:462) at com.android.sdklib.repository.legacy.LegacyDownloader.downloadAndStream(LegacyDownloader.java:82) at com.android.repository.impl.downloader.LocalFileAwareDownloader.downloadAndStream(LocalFileAwareDownloader.java:51) at com.android.repository.impl.manager.RemoteRepoLoaderImpl.lambda$fetchPackages$0(RemoteRepoLoaderImpl.java:140) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) at java.base/java.util.concurrent.FutureTask.run(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) Warning: Still waiting for package manifests to be fetched remotely. [CXX1300] CMake '3.22.1' was not found in SDK, PATH, or by cmake.dir property. [CXX1416] Could not find Ninja on PATH or in SDK CMake bin folders. [CXX1300] No valid CMake executable was found.
06-27
java.io.FileNotFoundException: https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json/plugins/htmlpublisher/427/htmlpublisher.hpi at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:2009) at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1614) at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:223) at hudson.model.UpdateCenter$UpdateCenterConfiguration.download(UpdateCenter.java:1348) Caused: java.io.IOException: Failed to load https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json/plugins/htmlpublisher/427/htmlpublisher.hpi to C:\Users\86131\.jenkins\plugins\htmlpublisher.jpi.tmp at hudson.model.UpdateCenter$UpdateCenterConfiguration.download(UpdateCenter.java:1363) Caused: java.io.IOException: Failed to download from https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json/plugins/htmlpublisher/427/htmlpublisher.hpi at hudson.model.UpdateCenter$UpdateCenterConfiguration.download(UpdateCenter.java:1390) at hudson.model.UpdateCenter$DownloadJob._run(UpdateCenter.java:2038) at hudson.model.UpdateCenter$InstallationJob._run(UpdateCenter.java:2366) at hudson.model.UpdateCenter$DownloadJob.run(UpdateCenter.java:2012) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) at hudson.remoting.AtmostOneThreadExecutor$Worker.run(AtmostOneThreadExecutor.java:121) at java.base/java.lang.Thread.run(Thread.java:1583)
最新发布
09-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值