当数据从接收到的响应流中读取时,无法在try / catch中捕获monotouch webexception

时间:2013-01-14 10:07:42

标签: c# mono xamarin.ios system.net

我的IO应用程序向服务发送请求,该服务以指定的频率发送一些数据(通常每秒2或3次)。 15或20分钟后,我得到了WebException,它无法被try / catch块捕获。使用BinaryReader.ReadBytes()读取数据时抛出异常。这是堆栈:

System.Net.WebException: The operation has timed out.
at System.Net.WebConnectionStream.Read (System.Byte[] buffer, Int32 offset, Int32 size) [0x00048] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnectionStream.cs:330
at System.IO.BinaryReader.ReadBytes (Int32 count) [0x00051] in /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.IO/BinaryReader.cs:318
at JpegProcessorLib.FramesProvider.OnGetResponse (IAsyncResult asyncResult) [0x0013f] in /Users/User/Projects/NvrViewer/NvrViewer/Streaming/FramesProvider.cs:146
at System.Net.WebAsyncResult.CB (System.Object unused) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebAsyncResult.cs:148

以下是代码:

private void OnGetResponse (IAsyncResult asyncResult)
    {
        if (!this.isStreamActive) 
        {
            return;
        }

        HttpWebResponse resp = null;
        byte[] buff = null;

        byte[] imageBuffer = new byte[this.approximatelyImageSize];
        Stream stream = null;

        // get the response
        HttpWebRequest req = (HttpWebRequest)asyncResult.AsyncState;
        req.GetRequestStream().Close();
        resp = (HttpWebResponse)req.EndGetResponse (asyncResult);

        // find our magic boundary value
        string contentType = resp.Headers ["Content-Type"];

        if (!string.IsNullOrEmpty (contentType) && !contentType.Contains ("="))
        {
            this.PublishFrameReceivingResult(new FrameProviderException ("Invalid content-type header. The camera is likely not returning a proper MJPEG stream."));
            return;         
        }

        string boundary = resp.Headers["Content-Type"].Split('=')[1].Replace("\"", "");
        byte[] boundaryBytes = Encoding.UTF8.GetBytes(boundary.StartsWith("--") ? boundary : "--" + boundary);

        try
        {
            stream = resp.GetResponseStream();
        }
        catch(ProtocolViolationException)
        {
            this.PublishFrameReceivingResult(new FrameProviderException ("Payload was not received from the server"));
            return;
        }

        BinaryReader br = new BinaryReader(stream);
        isStreamActive = true;

        try
        {
            buff = br.ReadBytes(this.frameWidth);   
        }
        catch(WebException)
        {
            br.Close();
            resp.Close();
            return;
        }

        while (isStreamActive)
        {
            int size;

            // find the JPEG header
            int imageStart = buff.Find(JpegHeader);

            if(imageStart != -1)
            {
                // copy the start of the JPEG image to the imageBuffer
                size = buff.Length - imageStart;
                Array.Copy(buff, imageStart, imageBuffer, 0, size);

                while(true)
                {
                    /*

> System.Net.WebException: The operation has timed out.   at System.Net.WebConnectionStream.Read (System.Byte[] buffer, Int32
> offset, Int32 size) [0x00048] in
> /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebConnectionStream.cs:330
> at System.IO.BinaryReader.ReadBytes (Int32 count) [0x00051] in
> /Developer/MonoTouch/Source/mono/mcs/class/corlib/System.IO/BinaryReader.cs:318
> at JpegProcessorLib.FramesProvider.OnGetResponse (IAsyncResult
> asyncResult) [0x0013f] in
> /Users/User/Projects/NvrViewer/NvrViewer/Streaming/FramesProvider.cs:146
> at System.Net.WebAsyncResult.CB (System.Object unused) [0x00000] in
> /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/WebAsyncResult.cs:148

                    */

                    try
                    {
                        buff = br.ReadBytes(this.frameWidth);
                    }
                    catch
                    {
                        br.Close();
                        resp.Close();
                        return;
                    }

                    // find the boundary text
                    int imageEnd = buff.Find(boundaryBytes);
                    if(imageEnd != -1)
                    {
                        // copy the remainder of the JPEG to the imageBuffer
                        Array.Copy(buff, 0, imageBuffer, size, imageEnd);
                        size += imageEnd;

                        // create a single JPEG image
                        byte[] currentFrame = new byte[size];
                        Array.Copy(imageBuffer, 0, currentFrame, 0, size);

                        this.SaveImage(currentFrame);

                        // copy the leftover data to the start
                        Array.Copy(buff, imageEnd, buff, 0, buff.Length - imageEnd);

                        // fill the remainder of the buffer with new data and start over
                        byte[] temp = br.ReadBytes(imageEnd);

                        Array.Copy(temp, 0, buff, buff.Length - imageEnd, temp.Length);
                        break;
                    }

                    // copy all of the data to the imageBuffer
                    Array.Copy(buff, 0, imageBuffer, size, buff.Length);
                    size += buff.Length;
                }
            }
        }
        resp.Close();
    }

有人可以提供建议吗?

1 个答案:

答案 0 :(得分:0)

你有另一个不在try / catch处理程序中的ReadBytes:

byte[] temp = br.ReadBytes(imageEnd);

可能会抛出异常吗?