检查StreamReader是否有可用数据的非阻塞方法

时间:2014-10-21 19:36:18

标签: c# mono

我有一个StreamReader,我想知道是否有数据可用而不会阻塞该帖子。

我尝试了Peek方法,但是当没有可用数据时它会阻止。

using (StreamReader reader = new StreamReader(stream))
{
    if (reader.Peek() == -1) // Blocks here while there is no data and unblocks as soon as there is data.
    {

    }
}

如果我查看the mono code of the Peek() method,则会在评论中说明

    //
    // Peek can block:
    // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=96484
    //

不幸的是,该链接不再有效。

我发现herehereherehere Microsoft似乎有一个导致Peek阻止的错误。但所有这些帖子都很老了。我认为mono故意因为这个错误而Peek()阻止。

所以我有两个问题

  1. Microsoft是否仍然存在导致Peek()阻止的错误?如果不是,mono应该将Peek()的实现更改为非阻塞。
  2. 有没有其他方法可以检查StreamReader是否有数据可用而不会阻塞该线程?

2 个答案:

答案 0 :(得分:1)

好的,我只想说我真的不知道你要在这里完成什么。但是,从我所看到的情况来看,Peek方法必须阻止当前线程才能工作。这就是文档所说的内容:

  

Peek方法返回一个整数值以确定是否   文件的结尾,或发生了其他错误。这允许用户   首先检查返回值是否为-1,然后再将其转换为Char   类型。

因此,Peek只有在遇到错误或文件结尾时才返回-1。这有点令人困惑,因为可能没有涉及文件。该流可能是来自WebRequest的响应,在这种情况下,您尝试阅读的流的部分可能尚未下载。因此,Peek必须等到它完成,因为,从文档中不清楚,它返回从流中读取的第一个字节。

您发布的链接中提到的问题涉及使用相同StreamReader的多个线程,这不是您的情况。我也相信曾经有一个错误导致一个StreamReader等待输入阻止另一个,但我相信它已被修复。我不确定Mono实现的功能。

要回答您的问题,要在不阻止线程的情况下执行此操作,我会尝试以下操作:

  1. 把整个事情放到一个单独的线程中。然后,如果它被阻止,你就不会在乎它。
  2. 在任务中使用ReadAsync然后awaitContinueWith,使其无阻塞。
  3. 但是,正如评论中正确评论的那样,如果你把整个事情放到另一个线程中,你真的需要Peek吗?为什么不将它放入典型的while (Read(...)) { ... }块并处理数据呢?

答案 1 :(得分:0)

  1. 我无法给出任何答案,我没有任何具体案例可以复制和测试,显然源代码不可用。
  2. 使用.NET 4.5,您可以使用StreamReader类的ReadAsync方法