// 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
}
Task.Run(() => file.Read)
是否安全?换句话说,之前阻塞了线程池中的线程
read返回,而case2没有阻塞线程,如中所述
这篇文章:"There is no
thread"。httpClient().GetAsync()
默认情况下它使用异步IO线程,但是可能有GetAsync()分离另一个线程的实现?答案 0 :(得分:2)
您的大部分问题似乎都可以通过查看源代码来解答:
•说case1相当于Task.Run(()=> file.Read)是否安全?换句话说,线程池中的线程在读取返回之前被阻塞,而case2没有阻塞线程,如本文所述:"没有线程"。
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;
}
虽然我全心全意地同意"没有线索"文章,重要的是要避免过于字面意思。 IOCP比将线程专用于单个操作更有效,但它仍然涉及一些线程。它只是可以使用更小的线程池,任何给定的线程都能够响应大量操作的完成。
•何时使用case1(似乎是Microsoft Doc引入的默认方式)而不是case2。我在服务器端做了一些工作,case2可能会为传入请求提供更多备用线程吗?
这个问题实在太宽泛了,主要是基于意见的。但我认为你应该总是使用FileOptions.Asynchronous
来处理任何重要的文件I / O.如果由于某种原因你决定放弃并且仍然使用File.OpenRead()
,那么你就不应该费心去使用任何异步调用。
File.OpenRead()
非常方便。但是,如果您打算在File.OpenRead()
对象上调用异步方法(例如FileStream
,ReadAsync()
等,则永远不会使用BeginRead()
)。如果代码以异步方式运行非常重要,那么它的重要性足以确保它使用Windows中的高效异步功能实际执行此操作。
•这只发生在文件中吗?我针对httpClient()进行了测试。默认情况下,GetAsync()它使用异步IO线程,但是可能有GetAsync()分离另一个线程的实现?
您所询问的行为显然是针对您的代码示例中显示的唯一差异:使用File.Open()
(没有通过FileOptions.Asynchronous
)并使用带有FileStream
选项的FileOptions.Asynchronous
构造函数。因此,询问这是否只发生在文件中并不是真的有意义。根据定义,File.Open()
方法和FileStream
对象仅适用于文件。
那就是说,如果你要找到一个具有类似选项的不同类(即启用异步I / O),它肯定会完全相同(即没有启用选项就不使用IOCP),事实上是像HttpClient
或NetworkStream
构建在Socket
类之上,没有这样的选项,异步操作将通过该类的异步I /的实现O,总是使用IOCP。
所以,不......你不会在HttpClient
类中找到一个禁止使用IOCP进行异步操作的选项。
当然,您总是可以自己包装同步调用,使用主线程池而不是IOCP线程池,然后就像非异步FileStream
对象上的异步调用一样。 / p>