Почему я получаю сообщение «Время ожидания операции истекло», когда это не тайм-аут?

#c# #http #httpwebrequest #ip-camera

#c# #http #httpwebrequest #ip-камера

Вопрос:

Я создаю приложение, которое выполняет HTTP-запрос к IP-камере. Каждый раз, когда я выполняю 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, а ошибка.Сообщение «Время ожидания операции истекло».

* РЕДАКТИРОВАТЬ 2 *

Вот часть журнала, который я сделал с кодом. Как вы можете видеть, тайм-аут получен с очень небольшим временем отклика.

 C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00013.jpg --- BEGIN : 2011-10-27 08:16:46
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00010.jpg --- TOTALTIME:353
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00010.jpg --- END : 2011-10-27 08:16:47
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00006.jpg --- TOTALTIME:610
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00006.jpg --- END : 2011-10-27 08:16:47
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00008.jpg --- BEGIN : 2011-10-27 08:16:47
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00014.jpg --- BEGIN : 2011-10-27 08:16:47
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00009.jpg --- BEGIN : 2011-10-27 08:16:47
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00005.jpg --- TOTALTIME:996
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00005.jpg --- END : 2011-10-27 08:16:48
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00004.jpg --- TOTALTIME:800
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00004.jpg --- END : 2011-10-27 08:16:48
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00007.jpg === ERROR :22 | The operation has timed out
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00015.jpg --- BEGIN : 2011-10-27 08:16:48
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00014.jpg --- TOTALTIME:391
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00014.jpg --- END : 2011-10-27 08:16:49
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00009.jpg === ERROR :23 | The operation has timed out
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00008.jpg --- TOTALTIME:526
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00008.jpg --- END : 2011-10-27 08:16:50
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00012.jpg --- TOTALTIME:461
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00012.jpg --- END : 2011-10-27 08:16:50
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00015.jpg --- TOTALTIME:780
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00015.jpg --- END : 2011-10-27 08:16:50
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00011.jpg --- TOTALTIME:49
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00011.jpg --- END : 2011-10-27 08:16:50
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00009.jpg --- TOTALTIME:133
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00009.jpg --- END : 2011-10-27 08:16:50
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00007.jpg --- TOTALTIME:140
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00007.jpg --- END : 2011-10-27 08:16:51
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input1_00013.jpg === ERROR :28 | The operation has timed out
    C:UsersjfcoteAppDataLocalTempd1785720-afc6-4822-b02d-fdf6d2f2c0d1input2_00010.jpg --- BEGIN : 2011-10-27 08:16:56
  

Комментарии:

1. Вы уверены, что это тайм-аут HTTP? Возможно, это связано с частью ResponseStream вашего кода.

2. Какое фактическое исключение вы видите?

3. Это консольное приложение, веб-служба и т. Д.?

Ответ №1:

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 , но для нее нет начальной строки. Является ли ваша ListTest потокобезопасная коллекция? В противном случае два потока, обновляющие его одновременно, вполне могут повредить список.

Кроме того, вы сказали, что ваш код отправляет запрос каждые 500 мс. Но в вашем журнале отображаются три запроса за один односекундный период.

Конечно, это не объясняет тайм-аут, если только по какой-то причине ServicePointManager или что-то еще не решило отключить его из-за слишком большого количества невыполненных запросов. Вы можете просмотреть трассировку стека исключений, чтобы увидеть, где было вызвано исключение тайм-аута.

Кроме того, вы могли бы рассмотреть возможность изменения вашего кода, чтобы он никогда не делал другого запроса к камере, пока не будет выполнен первый. Таким образом, вместо таймера, который срабатывает каждые 500 мс, вы запускаете одноразовый таймер с задержкой в 500 мс. Обратный вызов таймера получает изображение, а затем повторно инициализирует таймер еще на 500 мс. Таким образом, никогда не остается более одного невыполненного запроса на изображение, и вы избегаете странных проблем параллелизма. В нынешнем виде изображения могут отображаться не по порядку.

Я думаю, у вас проблемы с параллелизмом. Если несколько потоков могут выполнять этот код одновременно (вы указали, что это возможно), то ваш ListTest может быть поврежден, если это не какой-то потокобезопасный список.

Комментарии:

1. Привет! По вашему наблюдению, это была урезанная версия журнала, в которой отсутствовала некоторая информация. Но я нашел проблему, и вы были правы в своем редактировании: ServicePointManager использовался в одном потоке, но не в другом. Когда одновременно выполнялось более 2 соединений (значение по умолчанию), оно отправляло тайм-аут. Большое спасибо, что указали на это.