我想知道这样一种情况: Read(char[],int,int)无法返回请求的所有字符,而ReadBlock()则按预期返回所有字符(例如,当StreamReader处理FileStream对象的实例时)。
发布于 2010-12-01 07:47:36
在实践中,当使用StreamReader时,这只可能发生在可能会延迟一段时间的流中-例如,人们在这里提到的网络流。
然而,一般来说,对于TextReader,您可以预期它会在任何时候发生(包括在.NET的未来版本中可能在当前没有发生的情况下-在FileStream上支持的StreamReader没有文档记录的情况下,它不会发生,所以不能保证它不会在未来发生)。
特别是,在很多情况下,如果实现者可以通过清空当前缓冲区来部分完成调用,或者在执行只能返回较少字符的操作之前,使用请求的数量作为传递给后备源(流或另一个TextReader)的数量,则更容易(更简单、更可靠、可能更有效的代码的连锁反应)不返回请求的数量。
现在,回答有关“何时使用StreamReader.ReadBlock()?”的实际问题。(或者更一般地说,何时使用TextReader.ReadBlock())。请牢记以下几点:
Read()和ReadBlock()都保证返回至少一个字符,除非读取了整个源代码。如果存在挂起的content.Read()会做的是浪费的,因为它循环了wasteful.ReadBlock(),Read()返回的字符少于请求的字符的情况通常是另一个线程正在获取将为下一次调用填充缓冲区的内容的情况,或者在内容尚不存在的地方(例如,用户输入或另一台机器上的挂起操作)-在处理部分结果,然后在完成时再次调用Read()时,有更好的总体并发性。所以。如果您可以用部分结果做一些有用的事情,那么调用Read()并处理您得到的结果。特别是,如果您正在遍历和处理每个Read()的结果,那么就这样做,而不是使用ReadBlock()。
一个值得注意的例子是,如果您正在构建自己的TextReader,并且该A由另一个A支持。除非算法确实需要一定数量的字符才能工作,否则调用ReadBlock()是没有意义的--只要从Read()调用中返回尽可能多的内容,并让调用代码在需要时调用ReadBlock()即可。
特别是,请注意以下代码:
char buffer = char[4096];
int len = 0;
while((len = tr.ReadBlock(buffer, 0 , 4096)) != 0)
DoSomething(buffer, 0, len);可以重写为:
char buffer = char[4096];
for(int len = tr.Read(buffer, 0, 4096); len != 0; len = tr.Read(buffer, 0, 4096))
DoSomething(buffer, 0, len);它有时可能会使用较小的大小调用DoSomething(),但如果有另一个线程参与为下一次Read()调用提供数据,它也可以具有更好的并发性。
然而,在大多数情况下,收益并不是很大。如果您确实需要一定数量的字符,那么请调用ReadBlock()。最重要的是,在Read()具有与ReadBlock()相同的结果的情况下,ReadBlock()检查的开销是,非常轻微的。不要试图在给定的情况下猜测Read()是否安全;如果它需要ReadBlock()的保证,那么就使用ReadBlock()。
发布于 2010-09-28 15:54:18
这是网络流上的一个主要问题,特别是如果流数据非常大,并且提供流的服务器将其作为分块输出(例如,在超文本传输协议中非常典型),因为对Read()的调用,即,一旦达到状态,就读取单个字符,使用参数调用-1 \f25 Read(char[], int, int) -1\f6,如果达到-1\f25 EOS -1\f6,则调用的字符数等于或小于要求的字符数,然后返回读取的字符数,如果达到-1\f25 EOS -1\f6,则返回0
而ReadBlock()会等待数据流中的数据可用,所以你永远不会遇到这个问题。
另一件要注意的事情是,这两种表单都读取最大字符数,如果没有那么多可用字符,则不能保证返回那么多字符
不久前,当我在读取HTTP stream时遇到问题时,我问了一个类似主题的问题-- Reading from a HttpResponseStream fails
https://stackoverflow.com/questions/3810455
复制相似问题