Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当NetworkStream.Read(字节[],int,int)需要返回-1时,它将中止()它正在运行的线程?_C#_Networking_Stream - Fatal编程技术网

C# 当NetworkStream.Read(字节[],int,int)需要返回-1时,它将中止()它正在运行的线程?

C# 当NetworkStream.Read(字节[],int,int)需要返回-1时,它将中止()它正在运行的线程?,c#,networking,stream,C#,Networking,Stream,上述代码设计用于在单独的线程上运行时从TcpClient检索消息Read方法工作正常,直到它应该返回-1以指示不再有任何内容可读取;相反,它只是在没有任何明显原因的情况下终止它正在运行的线程——使用调试器跟踪每个步骤表明它只是在该行之后停止运行 我还尝试用try。。。捕获,但未取得多大成功 这可能是什么原因造成的 编辑:我试过了 NetworkStream stream = socket.GetStream(); if (stream.CanRead)

上述代码设计用于在单独的线程上运行时从
TcpClient
检索消息
Read
方法工作正常,直到它应该返回-1以指示不再有任何内容可读取;相反,它只是在没有任何明显原因的情况下终止它正在运行的线程——使用调试器跟踪每个步骤表明它只是在该行之后停止运行

我还尝试用
try。。。捕获
,但未取得多大成功

这可能是什么原因造成的

编辑:我试过了

        NetworkStream stream = socket.GetStream();

        if (stream.CanRead)
        {
            while (true)
            {
                int i = stream.Read(buf, 0, 1024);
                result += Encoding.ASCII.GetString(buf, 0, i);
            }
        }
感谢@JonSkeet,但问题仍然存在。线程终止于
read

EDIT2:我像这样修改了代码,它成功了

        NetworkStream stream = socket.GetStream();

    if (stream.CanRead)
    {
        while (true)
        {
            int i = stream.Read(buf, 0, 1024);
            if (i == 0)
            {
                break;
            }
            result += Encoding.ASCII.GetString(buf, 0, i);
        }
    }
我认为问题很简单,我只是想得不够透彻。谢谢大家看这个

否,当没有可读取内容时返回0,而不是-1:

返回值
读入缓冲区的总字节数。如果当前有那么多字节不可用,则该值可以小于请求的字节数;如果已到达流的末尾,则该值可以小于零(0)


我的猜测是,实际上,没有抛出异常,线程也没有被中止——但它只是永远循环。如果在调试器中单步执行,您应该能够看到这一点。无论发生什么情况,您的“愉快”终止条件将永远不会达到…

在我看来,它只是在阻塞,即在流的末尾等待。要返回非正数,必须关闭流,即调用方不仅发送了数据,还关闭了出站套接字。否则,系统无法区分“等待数据包到达”和“流结束”

如果呼叫者只发送一条消息,他们应该在发送后关闭出站套接字(他们可以保持入站套接字打开以获得回复)


如果调用方正在发送多条消息,则必须使用帧方法来读取单个子消息。对于基于文本的协议,这通常意味着“搜索换行符”。

由于您试图从流中读取ASCII字符,请查看以下可能更简单的方法:

    while (stream.DataAvailable)
    {
        int i = stream.Read(buf, 0, 1024);
        result += Encoding.ASCII.GetString(buf, 0, i);
    }
public IEnumerable可读行(流)
{
使用(StreamReader=newstreamreader(stream,Encoding.ASCII))
{
而(!reader.EndOfStream)
产生返回reader.ReadLine();
}
}
虽然这可能不是您想要的,但重点是:

  • 使用
    StreamReader
    为您完成所有繁重的工作
  • 使用带有
    的while循环!reader.EndOfStream
    在流中循环
  • 如果希望将块读入缓冲区并附加到结果中,您仍然可以使用
    reader.Read(buffer,01024)
    。请注意,这些将是
    char[]
    块,而不是
    byte[]
    块,这可能是您想要的

您说“我也尝试过用try…catch封装它,但没有多大成功。”-我们可以看看您是如何做到的吗?请重新编辑;不要为此使用
DataAvailable
;这并不意味着你认为它会做什么,而且通常会导致数据错误。
DataAvailable
的唯一有效用途是决定“我应该以同步还是异步的方式进行下一次读取”之类的事情。它与您的编辑一起工作是偶然的;对于您的场景,这不是一个可靠的解决方案。您可能希望使用我的网络库(),这样您就不必自己编写网络层了。@MarcGravel我明白您的意思了。因此,我在
while
循环之前额外添加了两行
inti=stream.Read(…)
result+=…
,以确保流与下一个传入数据包同步。当我100%确定有人正在向我发送数据包时,将调用此方法。@Kenny“packet”不是“send”的同义词;你能得到的可能是:一整条信息;几个完整的消息;半封信;一个字节;一条消息的结尾、整个第二条消息和第三条消息的开头;各种其他的疯狂。说真的,使用DataAvailable,或者从数据包的角度考虑是一个错误。您必须从流的角度思考,并应用“框架”方法。
public IEnumerable<string> ReadLines(Stream stream)
{
    using (StreamReader reader = new StreamReader(stream, Encoding.ASCII))
    {
        while (!reader.EndOfStream)
            yield return reader.ReadLine();
    }
}