简体   繁体   English

为什么不是超时,为什么会收到“操作已超时”?

[英]Why do I receive “The operation has timed out” when it is not a timeout?

I'm doing an application that do HTTP request to an IP camera. 我正在做一个向IP摄像机发出HTTP请求的应用程序。 Each time I do an HTTP request, I receive a picture that draw on the screen. 每次执行HTTP请求时,都会收到一幅画在屏幕上的图片。 All this process is done like this: 所有这些过程都是这样完成的:

  1. I have a timer that is called each 500 ms. 我有一个称为500毫秒的计时器。
  2. The code in the timer call a thread that do an http request. 计时器中的代码调用执行http请求的线程。

So there is a big possibility that when the timer is called, the http request is not completely done and it's ok like that. 因此,很有可能在调用计时器时,http请求没有完全完成,这样就可以了。

The problem is that sometime, for an unknown reason, I receive the exception "The operation has timed out". 问题是,由于某种未知原因,有时我会收到异常“操作已超时”。 So I did a log of the operation. 所以我做了一个操作日志。 I log the time before the http request and the time after. 我记录了http请求之前的时间和之后的时间。 It's always arround 300-400 ms. 总是300-400毫秒左右。 I also did a log in the exception and my big surprise was that the logged time is like 24 or 76 ms. 我也做了一个例外记录,令我惊讶的是记录的时间大约是24或76毫秒。 My timeout is set to 5000 ms so it should never timeout! 我的超时设置为5000毫秒,因此永远不要超时!

In all my test, I've never found a logged time bigger than 800 ms and that's way under the set timeout. 在我的所有测试中,我从未发现记录的时间大于800毫秒,而这是在设置的超时时间内。

Is there any other reason that could explain the error "Operation has timed out"? 还有其他原因可以解释错误“操作已超时”吗? I also try ServicePointManager.DefaultConnectionLimit = 200; 我也尝试ServicePointManager.DefaultConnectionLimit = 200; but it doesn't change anything. 但它并没有改变任何东西。

Thanks a lot! 非常感谢!

Here is the code that is threaded. 这是线程化的代码。 The ListTest is the logger, each line is then printed to a file. ListTest是记录器,然后将每一行打印到一个文件中。

StructTakePicture structTP = (StructTakePicture)structTakePicture;
ServicePointManager.DefaultConnectionLimit = 200; 
string strFileName = structTP.FolderGUID + "input" + GetNumeroPhoto(structTP.Cam.ID, structTP.NumPhoto) + ".jpg";
DateTime dateDebut = DateTime.Now;
try
{
    ListTest.Add(strFileName + " --- BEGIN : " + dateDebut.ToString()); 

    WebRequest WebRequestObject = HttpWebRequest.Create(String.Format("http://{0}/mjpg/snapshot.cgi?camera={1}", structTP.Cam.TotalIP, structTP.Cam.View));
    WebRequestObject.Timeout = 5000;
    WebRequestObject.Credentials = new NetworkCredential("admin", "admin");
    HttpWebResponse ResponseObject = (HttpWebResponse)WebRequestObject.GetResponse();

    string strTypeRetour = ResponseObject.ContentType;

    if (strTypeRetour == "image/jpeg")
    {
        MemoryStream memoryStream = new MemoryStream(0x10000);

        using (Stream responseStream = WebRequestObject.GetResponse().GetResponseStream())
        {
            byte[] buffer = new byte[0x1000];
            int bytes;
            while ((bytes = responseStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                memoryStream.Write(buffer, 0, bytes);
            }

            ResponseObject.Close();
        }

        byte[] response = memoryStream.ToArray();
        Image img = byteArrayToImage(response);


        img.Save(strFileName);
        structTP.StopEverything = false;
        DateTime dateFin = DateTime.Now;
        TimeSpan span = dateFin.Subtract(dateDebut);
        ListTest.Add(strFileName + " --- TOTALTIME:" + span.Milliseconds.ToString());
        ListTest.Add(strFileName + " --- END : " + dateFin.ToString());
    }
}
catch (System.Net.WebException err)
{
    structTP.StopEverything = true;
    DateTime dateFin = DateTime.Now;
    TimeSpan span = dateFin.Subtract(dateDebut);
    ListTest.Add(strFileName + " === ERROR :" + span.Milliseconds + " | " + err.Message);
}

* EDIT * *编辑*

To answer the comments, the error I get is in the System.Net.WebException and the err.Message is "Operation has timed out". 为了回答评论,我得到的错误是在System.Net.WebException中,而err.Message是“操作已超时”。

* EDIT 2 * *编辑2 *

Here is a part of a log I did with the code. 这是我对代码所做的日志的一部分。 As you can see, the timeout is received with very tiny response time. 如您所见,超时的响应时间非常短。

C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00013.jpg --- BEGIN : 2011-10-27 08:16:46
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00010.jpg --- TOTALTIME:353
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00010.jpg --- END : 2011-10-27 08:16:47
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00006.jpg --- TOTALTIME:610
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00006.jpg --- END : 2011-10-27 08:16:47
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00008.jpg --- BEGIN : 2011-10-27 08:16:47
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00014.jpg --- BEGIN : 2011-10-27 08:16:47
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00009.jpg --- BEGIN : 2011-10-27 08:16:47
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00005.jpg --- TOTALTIME:996
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00005.jpg --- END : 2011-10-27 08:16:48
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00004.jpg --- TOTALTIME:800
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00004.jpg --- END : 2011-10-27 08:16:48
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00007.jpg === ERROR :22 | The operation has timed out
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00015.jpg --- BEGIN : 2011-10-27 08:16:48
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00014.jpg --- TOTALTIME:391
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00014.jpg --- END : 2011-10-27 08:16:49
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00009.jpg === ERROR :23 | The operation has timed out
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00008.jpg --- TOTALTIME:526
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00008.jpg --- END : 2011-10-27 08:16:50
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00012.jpg --- TOTALTIME:461
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00012.jpg --- END : 2011-10-27 08:16:50
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00015.jpg --- TOTALTIME:780
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00015.jpg --- END : 2011-10-27 08:16:50
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00011.jpg --- TOTALTIME:49
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00011.jpg --- END : 2011-10-27 08:16:50
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00009.jpg --- TOTALTIME:133
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00009.jpg --- END : 2011-10-27 08:16:50
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00007.jpg --- TOTALTIME:140
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00007.jpg --- END : 2011-10-27 08:16:51
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input1_00013.jpg === ERROR :28 | The operation has timed out
    C:\Users\jfcote\AppData\Local\Temp\d1785720-afc6-4822-b02d-fdf6d2f2c0d1\input2_00010.jpg --- BEGIN : 2011-10-27 08:16:56

The Timeout value you're setting is the amount of time for the GetResponse to respond. 您设置的Timeout值是GetResponse响应的时间。 The HttpWebRequest also has a ReadWriteTimeout value that is used when reading or writing. HttpWebRequest还具有ReadWriteTimeout值,该值在读取或写入时使用。 You're not setting ReadWriteTimeout , so it's possible that GetResponse is returning within the timeout, but the read is timing out. 您未设置ReadWriteTimeout ,因此GetResponse有可能在超时内返回,但读取超时。

I would suggest you try the following modification: 我建议您尝试以下修改:

HttpWebRequest WebRequestObject = (HttpWebRequest)HttpWebRequest.Create(String.Format("http://{0}/mjpg/snapshot.cgi?camera={1}", structTP.Cam.TotalIP, structTP.Cam.View));
WebRequestObject.Timeout = 5000;
WebRequestObject.ReadWriteTimeout = 5000;

Additional observations: 其他观察:

Your log is incomplete, for example, there's an ERROR for file input1_0007 , but no BEGIN line for it. 您的日志不完整,例如,文件input1_0007出现错误,但没有BEGIN行。 Is your ListTest a thread-safe collection? 您的ListTest是线程安全的集合吗? If not, two threads updating it at the same time could very well corrupt the list. 如果没有,那么两个线程同时更新它可能会破坏列表。

Also, you said that your code is making a request every 500 ms. 另外,您说您的代码每500毫秒发出一个请求。 But your log shows three requests within a single one-second period. 但是您的日志在一个一秒钟的时间内显示了三个请求。

Granted, that doesn't explain the timeout, unless for some reason the ServicePointManager or something else decided to kill it because of too many outstanding requests. 当然,这不能解释超时,除非出于某些原因, ServicePointManager或其他原因由于未完成的请求太多而决定终止它。 You might look at the exception stack trace to see where the timeout exception was thrown. 您可能会查看异常堆栈跟踪,以了解在何处抛出了超时异常。

Also, you might consider changing your code so that it never makes another request to the camera until the first one is done. 另外,您可能会考虑更改代码,以便在第一个请求完成之前,它不会再向摄像机发出其他请求。 So instead of a timer that fires every 500 ms, you start a one-shot timer with a 500 ms delay. 因此,您可以启动具有500毫秒延迟的单发计时器,而不是每500毫秒触发一次的计时器。 The timer callback gets the picture and then re-initializes the timer for another 500 ms. 计时器回调获取图片,然后在另外500 ms内重新初始化计时器。 This way, there is never more than one outstanding request for a picture, and you avoid weird concurrency problems. 这样,对图片的请求就不会超过一个,并且可以避免奇怪的并发问题。 As it stands now, it's possible for pictures to be displayed out of order. 就目前情况而言,图片可能会乱序显示。

I think you're having concurrency problems. 我认为您遇到了并发问题。 If multiple threads can be executing this code at the same time (you indicated that it is possible), then your ListTest can get corrupted unless it's a thread-safe list of some kind. 如果多个线程可以同时执行此代码(您指出有可能),则ListTest可能会损坏,除非它是某种类型的线程安全列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM