Я не уверен насчет вашего первого примера кода, где вы используете WebClient.UploadValues, на самом деле этого недостаточно, не могли бы вы вставить больше окружающего кода? Что касается вашего кода WebRequest, здесь есть две вещи:
Вы запрашиваете только заголовки ответа **, вы никогда не читаете тело ответа, открывая и читая (до конца) ResponseStream. Из-за этого клиент WebRequest услужливо оставляет соединение открытым, ожидая, что вы запросите тело в любой момент. Пока вы не прочитаете тело ответа до завершения (которое автоматически закроет вам поток), очистите и закроете поток (или экземпляр WebRequest) или подождите, пока GC выполнит свою задачу, ваше соединение останется открытым.
У вас по умолчанию максимальное количество активных подключений к одному хосту 2. Это означает, что вы используете первые два подключения, а затем никогда не избавляетесь от них, так что ваш клиент не получает возможность завершить следующий запрос до того, как он достигнет своего тайм-аута (например, в миллисекундах, поэтому вы установили его на 0,2 секунды - по умолчанию все должно быть в порядке).
Если вы не хотите, чтобы тело ответа (или вы только что загрузили или отправили что-то и не ожидали ответа), просто закройте поток или клиент, который закроет поток для вас.
Самый простой способ исправить это - убедиться, что вы используете блоки на одноразовых предметах:
for (int i = 0; i < ops1; i++)
{
Uri myUri = new Uri(site);
WebRequest myWebRequest = WebRequest.Create(myUri);
//myWebRequest.Timeout = 200;
using (WebResponse myWebResponse = myWebRequest.GetResponse())
{
// Do what you want with myWebResponse.Headers.
} // Your response will be disposed of here
}
Другое решение - разрешить 200 одновременных подключений к одному хосту. Однако, если вы не планируете многопоточность этой операции, чтобы вам потребовалось несколько одновременных подключений, это вам не очень поможет:
ServicePointManager.DefaultConnectionLimit = 200;
Когда вы получаете тайм-ауты в коде, лучше всего попытаться воссоздать этот тайм-аут за пределами вашего кода. Если вы не можете, проблема, вероятно, кроется в вашем коде. Для этого я обычно использую cURL или просто веб-браузер, если это простой запрос GET.
** На самом деле, вы фактически запрашиваете первую порцию данных из ответа, которая содержит заголовки HTTP, а также начало тела. Вот почему можно прочитать информацию заголовка HTTP (например, Content-Encoding, Set-Cookie и т. Д.) Перед чтением из выходного потока. Когда вы читаете поток, дальнейшие данные извлекаются с сервера. Соединение WebRequest с сервером остается открытым до тех пор, пока вы не достигнете конца этого потока (фактически закрывая его, поскольку он не доступен для поиска), не закрывайте его вручную или он удаляется. Подробнее об этом здесь .