2011-10-26 124 views
0

我正在做一個應用程序,做一個IP攝像頭的HTTP請求。每次我做一個HTTP請求時,我都會收到一張在屏幕上繪製的圖片。所有這些過程都是這樣完成的:爲什麼在不是超時時收到「操作超時」?

  1. 我有一個計時器,每500毫秒調用一次。
  2. 在定時器呼叫做一個http請求線程的代碼。

所以有一個很大的可能性,當計時器被調用時,http請求並沒有完全完成,這是好的那樣。

的問題是,有時,由於未知原因,我收到異常「操作超時」。所以我做了一個操作日誌。我記錄了http請求之前的時間和之後的時間。它總是在300-400毫秒之間。我也做了一個例外日誌,我的驚喜是記錄的時間是24或76毫秒。我的超時設置爲5000毫秒,所以它永遠不會超時!

在我所有的測試中,我從來沒有發現一個記錄時間超過800毫秒更大,這就是一套超時工作正在進行。

是否有可能解釋錯誤「操作超時」的任何其他原因?我也嘗試ServicePointManager.DefaultConnectionLimit = 200;,但它不會改變任何東西。

非常感謝!

這裏是螺紋的代碼。 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); 
} 

*編輯*

要回答的意見,我得到的錯誤是在System.Net.WebException和err.Message是「操作超時」。

* EDIT 2 *

這裏是一個日誌我的代碼做的一部分。正如你所看到的,超時時間非常短。

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 
+0

你確定它是一個HTTP超時?也許它與你的代碼的responseStream部分有關。 – Matthew

+0

你看到的實際例外是什麼? –

+0

請參閱上面的修改。 –

回答

3

Timeout值你設置是時間GetResponse響應量。 HttpWebRequest還具有ReadWriteTimeout值,該值在讀取或寫入時使用。您沒有設置ReadWriteTimeout,所以有可能GetResponse在超時時間內返回,但讀取超時。

我建議您嘗試以下修改:

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; 

補充意見:

你的日誌是不完整的,例如,有文件input1_0007一個錯誤,但沒有BEGIN行吧。你的ListTest是一個線程安全的集合嗎?如果不是,兩個線程同時更新它可能會損壞列表。

而且,你說你的代碼發出請求每隔500毫秒。但是你的日誌會在一秒鐘內顯示三個請求。

當然,這並不能解釋超時,除非由於某些原因ServicePointManager或其他因爲太多未完成的請求而決定殺死它。您可以查看異常堆棧跟蹤以查看超時異常的引發位置。

此外,您可能會考慮更改您的代碼,以便在完成第一個代碼之前,不會再向攝像機發出其他請求。因此,不是每500毫秒觸發一次的定時器,而是以500毫秒的延遲啓動一次性定時器。定時器回調獲取圖片,然後重新初始化另一個500毫秒的定時器。這樣,對於圖片永遠不會有一個以上的突出請求,並且避免了奇怪的併發問題。就目前而言,照片可能無序顯示。

我認爲你有併發問題。如果多個線程可以同時執行此代碼(您指出它可能),那麼您的ListTest可能會損壞,除非它是某種線程安全的列表。

+0

真的好主意,但不幸它不起作用。我添加了一個日誌的一部分,所以你可以看到。 –

+0

@DarkJaff:查看我更新的答案。 –

+0

嗨!爲了您的觀察,這是日誌的修剪版本,缺少一些信息。但是我發現了這個問題,並且您在編輯中是正確的:ServicePointManager在一個線程中使用,但不在另一個線程中使用。當更多的2(默認值)連接同時進行請求時,它發送超時。非常感謝您指出這一點。 –