为什么我收到“操作已超时”当它不是一个超时
本文关键字:超时 一个 操作 操作已超时 为什么 | 更新日期: 2023-09-27 18:12:33
我正在做一个应用程序,做HTTP请求到IP摄像机。每次执行HTTP请求时,我都会收到绘制在屏幕上的图片。所有这些过程都是这样完成的:
- 我有一个计时器叫做每500 ms.
- 定时器中的代码调用一个执行http请求的线程。
所以有一个很大的可能性,当计时器被调用时,http请求没有完全完成,它就像那样。
问题是,有时,由于未知的原因,我收到异常"操作已超时"。所以我做了一个对数运算。我记录了http请求之前和之后的时间。它总是在300-400毫秒左右。我也做了一个异常日志,我最大的惊喜是,记录的时间是24或76毫秒。我的超时设置为5000毫秒,所以它永远不会超时!
在我所有的测试中,我从来没有发现一个日志时间大于800毫秒,这是在设置超时。
是否有其他原因可以解释错误"Operation has timed out"?我也尝试了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);
}
* EDIT *
回答评论,我得到的错误是在system.net.webeexception和err。提示"操作超时"。
* 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
您正在设置的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
有一个ERROR,但没有BEGIN行。你的ListTest
是一个线程安全的集合吗?如果不是,两个线程同时更新它很可能会破坏列表。
还有,你说你的代码每500毫秒发出一个请求。但是你的日志显示在一秒钟内有三个请求。
当然,这并不能解释超时,除非由于某些原因ServicePointManager
或其他原因决定杀死它,因为太多未完成的请求。您可以查看异常堆栈跟踪,以查看抛出超时异常的位置。
另外,您可以考虑更改代码,以便在第一个请求完成之前永远不会向相机发出另一个请求。所以不是每500毫秒触发一次的计时器,而是启动一个延时500毫秒的单次计时器。计时器回调获取图片,然后再初始化计时器500毫秒。这样,就不会有超过一个未完成的图片请求,并且可以避免奇怪的并发问题。按照现在的情况,图片可能会乱放。
我认为你有并发问题。如果多个线程可以同时执行此代码(您指出这是可能的),那么ListTest
可能会损坏,除非它是某种类型的线程安全列表。