没有完成端口的异步 IO?
Async IO without completion port?
// 1-
using(FileStream file = File.Open("ConfusedDev", FileMode.Open)) {
await file.ReadAsync(buffer, 0, 1024);
Thread.Sleep(Timeout.Infinite); // threadpool shows 1 worker thread in use
}
// 2-
using(FileStream file = new FileStream("ConfusedDev", FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous)) {
await file.ReadAsync(buffer, 0, 1024);
Thread.Sleep(Timeout.Infinite); // threadpool shows 1 async IO thread in use
}
- 可以安全地说 case1 等同于
Task.Run(() => file.Read)
吗?也就是说,threadpool中的一个线程在被阻塞之前
读取 returns 而 case2 没有阻塞线程,如中所述
这个 post: "没有
线程.
- 什么时候使用case1(好像是
Microsoft Doc) 在案例 2 上。我正在服务器端做一些工作,case2 可能会为传入请求提供更多备用线程?
- 这是否只发生在文件上?我针对
httpClient().GetAsync()
进行了测试,默认情况下它使用异步 IO 线程,但也许有 GetAsync() 分拆另一个线程的实现?
您的大部分问题似乎只需查看源代码即可得到解答:
• Is it safe to say that case1 is equivalent of Task.Run(() => file.Read)? In other words, a thread in threadpool is blocked before read returns whereas case2 has no blocking thread as mentioned in this post: "There is no thread".
File.OpenRead()
不会将 FileOptions.Asynchronous
传递给 FileStream
构造函数,因此任何异步调用都是使用线程池中的阻塞 I/O 实现的。具体来说,对 ReadAsync()
的调用最终会调用 FileStream.BeginRead()
,如果实例不是使用 FileOptions.Asynchronous
创建的,它会将读取委托给 the base class BeginRead()
, which eventually executes this anonymous method as a task:
delegate
{
// The ReadWriteTask stores all of the parameters to pass to Read.
// As we're currently inside of it, we can get the current task
// and grab the parameters from it.
var thisTask = Task.InternalCurrent as ReadWriteTask;
Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
// Do the Read and return the number of bytes read
var bytesRead = thisTask._stream.Read(thisTask._buffer, thisTask._offset, thisTask._count);
thisTask.ClearBeginState(); // just to help alleviate some memory pressure
return bytesRead;
}
虽然我完全同意 "There is no thread" 文章,但重要的是要避免从字面上理解它。 IOCP 比将线程专用于单个操作更有效,但它仍然涉及一些 个线程。只是可以使用更小的线程池,并且任何给定的线程都能够响应更多操作的完成。
• When to use case1(seems to be the default way introduced by Microsoft Doc) over case2. I am doing some work on the server side, case2 probably give me more spare threads for incoming requests?
这个问题真的太宽泛了,而且主要是基于意见。但我认为您应该 始终 对任何重要文件 I/O 使用 FileOptions.Asynchronous
。如果出于某种原因你决定放弃它并使用 File.OpenRead()
,那么你不应该费心使用任何异步调用。
File.OpenRead()
对于做非常简单的同步 I/O 的短程序来说很方便也很好。但是你应该 永远不要 使用 File.OpenRead()
如果你打算然后调用 FileStream
对象上的异步方法(例如 ReadAsync()
, BeginRead()
, ETC。)。如果代码异步操作足够重要,那么使用 Windows.
中的高效异步功能来确保它确实这样做也很重要
• Does this only happen to files? I tested against httpClient().GetAsync() it uses async IO thread by default, but maybe there is implementation where GetAsync() spin off another thread?
显然,您所询问的行为特定于代码示例中显示的唯一区别:使用 File.Open()
(未通过 FileOptions.Asynchronous
)和使用 FileStream
构造函数与 FileOptions.Asynchronous
选项。所以问这是否只发生在文件上是没有意义的。 File.Open()
方法和 FileStream
对象根据定义仅适用于 文件 .
也就是说,如果您要找到一个具有相似选项的不同 class(即启用异步 I/O 或不启用),它肯定会以相同的方式工作(即不使用 IOCP 而不是选项已启用),实际上像 HttpClient
或 NetworkStream
是建立在 Socket
class 之上的,它没有这样的选项,异步操作将会继续通过 class 的异步实现 I/O,它始终使用 IOCP。
所以,不……您不会在 HttpClient
class 中找到禁用 IOCP 进行异步操作的选项。
当然,您始终可以自己包装同步调用,使用主线程池而不是 IOCP 线程池,然后它的行为就像对非异步 FileStream
对象的异步调用一样.
// 1-
using(FileStream file = File.Open("ConfusedDev", FileMode.Open)) {
await file.ReadAsync(buffer, 0, 1024);
Thread.Sleep(Timeout.Infinite); // threadpool shows 1 worker thread in use
}
// 2-
using(FileStream file = new FileStream("ConfusedDev", FileMode.Open, FileAccess.Read, FileShare.Read, 1024, FileOptions.Asynchronous)) {
await file.ReadAsync(buffer, 0, 1024);
Thread.Sleep(Timeout.Infinite); // threadpool shows 1 async IO thread in use
}
- 可以安全地说 case1 等同于
Task.Run(() => file.Read)
吗?也就是说,threadpool中的一个线程在被阻塞之前 读取 returns 而 case2 没有阻塞线程,如中所述 这个 post: "没有 线程. - 什么时候使用case1(好像是 Microsoft Doc) 在案例 2 上。我正在服务器端做一些工作,case2 可能会为传入请求提供更多备用线程?
- 这是否只发生在文件上?我针对
httpClient().GetAsync()
进行了测试,默认情况下它使用异步 IO 线程,但也许有 GetAsync() 分拆另一个线程的实现?
您的大部分问题似乎只需查看源代码即可得到解答:
• Is it safe to say that case1 is equivalent of Task.Run(() => file.Read)? In other words, a thread in threadpool is blocked before read returns whereas case2 has no blocking thread as mentioned in this post: "There is no thread".
File.OpenRead()
不会将 FileOptions.Asynchronous
传递给 FileStream
构造函数,因此任何异步调用都是使用线程池中的阻塞 I/O 实现的。具体来说,对 ReadAsync()
的调用最终会调用 FileStream.BeginRead()
,如果实例不是使用 FileOptions.Asynchronous
创建的,它会将读取委托给 the base class BeginRead()
, which eventually executes this anonymous method as a task:
delegate
{
// The ReadWriteTask stores all of the parameters to pass to Read.
// As we're currently inside of it, we can get the current task
// and grab the parameters from it.
var thisTask = Task.InternalCurrent as ReadWriteTask;
Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
// Do the Read and return the number of bytes read
var bytesRead = thisTask._stream.Read(thisTask._buffer, thisTask._offset, thisTask._count);
thisTask.ClearBeginState(); // just to help alleviate some memory pressure
return bytesRead;
}
虽然我完全同意 "There is no thread" 文章,但重要的是要避免从字面上理解它。 IOCP 比将线程专用于单个操作更有效,但它仍然涉及一些 个线程。只是可以使用更小的线程池,并且任何给定的线程都能够响应更多操作的完成。
• When to use case1(seems to be the default way introduced by Microsoft Doc) over case2. I am doing some work on the server side, case2 probably give me more spare threads for incoming requests?
这个问题真的太宽泛了,而且主要是基于意见。但我认为您应该 始终 对任何重要文件 I/O 使用 FileOptions.Asynchronous
。如果出于某种原因你决定放弃它并使用 File.OpenRead()
,那么你不应该费心使用任何异步调用。
File.OpenRead()
对于做非常简单的同步 I/O 的短程序来说很方便也很好。但是你应该 永远不要 使用 File.OpenRead()
如果你打算然后调用 FileStream
对象上的异步方法(例如 ReadAsync()
, BeginRead()
, ETC。)。如果代码异步操作足够重要,那么使用 Windows.
• Does this only happen to files? I tested against httpClient().GetAsync() it uses async IO thread by default, but maybe there is implementation where GetAsync() spin off another thread?
显然,您所询问的行为特定于代码示例中显示的唯一区别:使用 File.Open()
(未通过 FileOptions.Asynchronous
)和使用 FileStream
构造函数与 FileOptions.Asynchronous
选项。所以问这是否只发生在文件上是没有意义的。 File.Open()
方法和 FileStream
对象根据定义仅适用于 文件 .
也就是说,如果您要找到一个具有相似选项的不同 class(即启用异步 I/O 或不启用),它肯定会以相同的方式工作(即不使用 IOCP 而不是选项已启用),实际上像 HttpClient
或 NetworkStream
是建立在 Socket
class 之上的,它没有这样的选项,异步操作将会继续通过 class 的异步实现 I/O,它始终使用 IOCP。
所以,不……您不会在 HttpClient
class 中找到禁用 IOCP 进行异步操作的选项。
当然,您始终可以自己包装同步调用,使用主线程池而不是 IOCP 线程池,然后它的行为就像对非异步 FileStream
对象的异步调用一样.