Почему я получаю сообщение "Время ожидания истекло", если это не время ожидания? - PullRequest
0 голосов
/ 26 октября 2011

Я делаю приложение, которое делает 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 и сообщение об ошибке err.Message: «Операция истекла.»

* РЕДАКТИРОВАТЬ 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

1 Ответ

3 голосов
/ 27 октября 2011

Значение 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 может быть поврежден, если это не потокобезопасный список какого-либо вида.

...