Я кодирую многопоточный веб-искатель, который выполняет множество параллельных запросов httpwebrequests каждую секунду, используя сотни потоков, приложение отлично работает, но иногда (случайно) один из веб-запросов зависает на getResponseStream(), полностью игнорируя тайм-аут (это происходит, когда Я выполняю сотни запросов одновременно), поэтому процесс обхода никогда не заканчивается, странно, что с помощью скрипача это никогда не происходит, и приложение никогда не зависает, его очень сложно отлаживать, потому что это происходит случайным образом.
Я попытался установить
Keep-Alive = false
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
но я все еще получаю странное поведение, любые идеи?
благодаря
Код HttpWebRequest:
public static string RequestHttp(string url, string referer, ref CookieContainer cookieContainer_0, IWebProxy proxy)
{
string str = string.Empty;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
request.UserAgent = randomuseragent();
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "*/*";
request.CookieContainer = cookieContainer_0;
request.Proxy = proxy;
request.Timeout = 15000;
request.Referer = referer;
//request.ServicePoint.MaxIdleTime = 15000;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
List<byte> list = new List<byte>();
byte[] buffer = new byte[0x400];
int count = responseStream.Read(buffer, 0, buffer.Length);
while (count != 0)
{
list.AddRange(buffer.ToList<byte>().GetRange(0, count));
if (list.Count >= 0x100000)
{
break;
}
count = 0;
try
{
HERE IT HANGS SOMETIMES ---> count = responseStream.Read(buffer, 0, buffer.Length);
continue;
}
catch
{
continue;
}
}
//responseStream.Close();
int num2 = 0x200 * 0x400;
if (list.Count >= num2)
{
list.RemoveRange((num2 * 3) / 10, list.Count - num2);
}
byte[] bytes = list.ToArray();
str = Encoding.Default.GetString(bytes);
Encoding encoding = Encoding.Default;
if (str.ToLower().IndexOf("charset=") > 0)
{
encoding = GetEncoding(str);
}
else
{
try
{
encoding = Encoding.GetEncoding(response.CharacterSet);
}
catch
{
}
}
str = encoding.GetString(bytes);
// response.Close();
}
}
return str.Trim();
}
Свойство Timeout. Получает или задает значение тайм-аута в миллисекундах для методов GetResponse и GetRequestStream. " Значение по умолчанию - 100 000 миллисекунд (100 секунд).
Свойство ReadWriteTimeout: "Получает или устанавливает тайм-аут в миллисекундах при записи или чтении из потока". Значение по умолчанию - 300 000 миллисекунд (5 минут).
Вы устанавливаете Timeout
, но оставляете ReadWriteTimeout
по умолчанию, поэтому ваши чтения могут занять до пяти минут до тайминга. Вероятно, вы хотите установить ReadWriteTimeout
на меньшее значение. Вы также можете ограничить размер загружаемых данных. С помощью моего искателя я иногда натыкался на нескончаемый поток, который в итоге привел бы к исключению из памяти.
Что-то еще, что я заметил при сканировании, заключается в том, что иногда закрытие потока ответов будет зависать. Я обнаружил, что мне нужно было вызвать request.Abort
чтобы надежно завершить запрос, если я захочу выйти, прежде чем читать весь поток.
Ниже приведен код, который делает что-то подобное, он также используется для доступа к нескольким веб-сайтам, каждый вызов находится в другой задаче. Разница в том, что я только прочитал поток один раз, а затем проанализировал результаты. Это может быть способ обойти блокировку потока в случайном порядке или, по крайней мере, облегчить его отладку.
try
{
_webResponse = (HttpWebResponse)_request.GetResponse();
if(_request.HaveResponse)
{
if (_webResponse.StatusCode == HttpStatusCode.OK)
{
var _stream = _webResponse.GetResponseStream();
using (var _streamReader = new StreamReader(_stream))
{
string str = _streamReader.ReadToEnd();
В коде нет ничего очевидного.
Почему вы прокомментировали ответ.Close()?
Документация указывает, что соединения могут закончиться, если они явно не закрыты. Ответ, который может быть удален, может закрыть соединение, но просто освобождение всех ресурсов не оптимально, я думаю. Закрытие ответа также закроет поток, чтобы он был закрыт.
Система, зависающая без таймаута, может быть просто сетевой проблемой, создающей объект ответа мертвой утиной, или проблема связана с большим количеством потоков, что приводит к фрагментации памяти.
Глядя на все, что может создать шаблон, может помочь найти источник:
Хотите задать больше вопросов, но недостаточно репутации, поэтому можете только ответить.
Удачи!