先放两段代码:        private void beginReadStatus()
        {
            receiveDataBuffer = null;
            receiveDataBuffer = new Byte[this.tcpclient.ReceiveBufferSize];
            tcpstream.BeginRead(receiveDataBuffer, 0, receiveDataBuffer.Length, new AsyncCallback(doReadStatus), tcpstream);
        }
        private void doReadStatus(IAsyncResult ar)
        {
             Stream stream = (Stream)ar.AsyncState;
             if (stream.CanRead)
             {
                 int dataSize = tcpstream.EndRead(ar);
                 ……(业务代码)
                 tcpstream.BeginRead(receiveDataBuffer, 0, receiveDataBuffer.Length, new AsyncCallback(doReadStatus), tcpstream);
             }
        }这是个异步读的过程,在doReadStatus中stream.CanRead=true,但int dataSize = tcpstream.EndRead(ar)后dataSize=0,执行完业务代码后,再beginread,然后就又重复这个过程了,无限循环,导致cpu占用率很高。
不明白的是流(tcpstream)里数据大小为0,为什么还可以读?请真正明白的人帮忙解答下~

解决方案 »

  1.   

    canread恒为true吧.这么写肯定死循环了,你可以试试netstream的avaliable属性
      

  2.   

    canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?
      

  3.   

    canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?打个比方说, 你会看的懂书吧,可不代表你现在在看读书啊!明白?
      

  4.   

    canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?打个比方说, 你会看的懂书吧,可不代表你现在在看读书啊!明白?
    就是有一点不明白,为什么会一直循环,流里分明没有数据。beginread不是会在流里有数据时才触发它的回调函数吗?
      

  5.   

    canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?打个比方说, 你会看的懂书吧,可不代表你现在在看读书啊!明白?
    就是有一点不明白,为什么会一直循环,流里分明没有数据。beginread不是会在流里有数据时才触发它的回调函数吗?canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?打个比方说, 你会看的懂书吧,可不代表你现在在看读书啊!明白?
    就是有一点不明白,为什么会一直循环,流里分明没有数据。beginread不是会在流里有数据时才触发它的回调函数吗?你怎么知道流里没有数据?你别管其它,看看receiveDataBuffer 这个数组里是否有数据了。
      

  6.   

    canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?打个比方说, 你会看的懂书吧,可不代表你现在在看读书啊!明白?
    就是有一点不明白,为什么会一直循环,流里分明没有数据。beginread不是会在流里有数据时才触发它的回调函数吗?canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?打个比方说, 你会看的懂书吧,可不代表你现在在看读书啊!明白?
    就是有一点不明白,为什么会一直循环,流里分明没有数据。beginread不是会在流里有数据时才触发它的回调函数吗?你怎么知道流里没有数据?你别管其它,看看receiveDataBuffer 这个数组里是否有数据了。
    int dataSize = tcpstream.EndRead(ar)这句后,dataSize=0,然后执行业务代码,最后再beginRead,就立马又到doReadStatus这个回调函数里面了,而且endread后dataSize还是0,一直在循环,不解。。
      

  7.   

    看来你是第一次用到Socket编程(上面其它回复的人也是如此),有Socket编程经验的人都知道,当读取时返回0个字节,就说明对方中断的TCP连接,也就是单方面的连接放弃,否则读取方法将会阻塞,不会返回。此时你只要判断接收到的数据是否为0个字节,是的话,你也将当前TCP连接关闭,中断当前会话(如果是一次性的会话,那就说明对方发送数据结束)。这里单方面的连接放弃也可能是网络异常导致,因此数据的完整性验证需要自己单独做,例如再发送的数据开头添加一个4字节数据(int的长度),指明后面的数据有多长,用来验证是否完整。
      

  8.   

    连接要单方面断的话,endread那就会抛出个异常"主机被迫关闭一个连接"什么的,就不会返回0。。
      

  9.   

    what are you laughing?Because I forgot
      

  10.   

    what are you laughing?
    他有病,自己不懂装懂,还嘲笑别人。你要再不信,只能看官方说明了,本来我是懒得去找,没想到固执的人就是顽固不化。
    http://msdn.microsoft.com/ZH-CN/library/vstudio/system.net.sockets.networkstream.read(v=vs.110).aspx
    备注
    该方法将数据读入 buffer 参数并返回成功读取的字节数。 如果没有可读取的数据,则 Read 方法返回 0。 Read 操作将读取尽可能多的可用数据,直到达到 size 参数指定的字节数为止。 如果远程主机关闭了连接并且已接收到所有可用数据,Read 方法将立即完成并返回零字节。
      

  11.   

    canread在流断了就会为false。现在问题是为什么流里没东西还会一直在执行doReadStatus这个方法?不是只有当异步请求来时才会异步读取吗?
    流断了当然会返回false了,流里无数据和流断了是两个概念啊.你需要判断的是流里有无数据,若有则读取
      

  12.   

    你说的没错,但楼主的程序陷入死循环是因为链接未断,而且流中无数据.楼主的判断是用的canread属性,这个属性只能说明流的状态,不能说明其中是否有数据
      

  13.   

    what are you laughing?
    他有病,自己不懂装懂,还嘲笑别人。你要再不信,只能看官方说明了,本来我是懒得去找,没想到固执的人就是顽固不化。
    http://msdn.microsoft.com/ZH-CN/library/vstudio/system.net.sockets.networkstream.read(v=vs.110).aspx
    备注
    该方法将数据读入 buffer 参数并返回成功读取的字节数。 如果没有可读取的数据,则 Read 方法返回 0。 Read 操作将读取尽可能多的可用数据,直到达到 size 参数指定的字节数为止。 如果远程主机关闭了连接并且已接收到所有可用数据,Read 方法将立即完成并返回零字节。其实我很少骂人的,但我真的很想骂你SB。
    我嘲笑你了吗? SB,
    我笑我自己忘记了。 再送你两字SB
      

  14.   

    追问一下,关键是我的连接没有断啊,我是用我机器上的一个程序连接这个程序,不可能连接断了,我也测了啊。。那么这样一直endread返回0是什么原因?
      

  15.   

    你机器上面的程序是否有源码?如果有,把连接部分的代码贴出来就知道了,如果没有,你可以试试在返回0字节后进行发送数据,因为发送数据的时候,如果连接断开就会报错。
    最后说明下,对于网络流,CanRead属性在建立连接后永远为true,所以那个是无需判断的。对于普通流,例如内存流,判断是否读取结束就是判断返回的字节数是否为0,对于读取到末尾的内存流,你再读取也不会报错,只是总是返回给你0字节。因此微软将Socket流化处理时也采用了该原理,判断网络是否断开就用返回的字节数是否为0来表示,如果TCP连接还保持着,Read或BeginRead方法就会一直等待下面可能进来的数据,不会将0字节返回给用户。返回0字节就意味着肯定不会再有数据进来了,那就是TCP连接断开了。