c# - tres - suma de numeros en lenguaje c
Multiplicando un gran número de solicitudes web en c# (4)
No está cerrando la solicitud web, lo que podría causar que la conexión se abra innecesariamente durante mucho tiempo. Esto suena como un trabajo perfecto para Parallel.Net''s Parallel.Foreach, solo asegúrate de indicar cuántos hilos quieres que se ejecuten en
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 10;
Parallel.ForEach(folderPathList, parallelOptions, folderPathList =>
{
using(WebRequest request = WebRequest.Create(folderPath))
{
request.Credentials = DefaultCredentials;
request.Method = "MKCOL";
GetResponse request = WebRequest.Create(folderPath);
request.Credentials = DefaultCredentials;
request.Method = "MKCOL";
using (WebResponse response = request.GetResponse());
}
});
Otra cosa a tener en cuenta es maxConnections, asegúrese de configurarlo en su app.config:
<configuration>
<system.net>
<connectionManagement>
<add address = "*" maxconnection = "100" />
</connectionManagement>
</system.net>
</configuration>
Por supuesto, en un escenario del mundo real, tendría que agregar try-catch y volver a intentar las conexiones que podrían llegar a un código más complicado
Tengo un programa en el que necesito crear un gran número de carpetas en un sitio externo de sharepoint (significado externo no puedo usar el modelo de objetos de sharepoint). Las solicitudes web funcionan bien para esto, pero simplemente hacerlas una a la vez (enviar solicitud, esperar respuesta, repetir) es bastante lento. Decidí multihilo las solicitudes, para tratar de acelerarlo. El programa se ha acelerado considerablemente, pero después de cierto tiempo (entre 1 y 2 minutos más o menos), las excepciones de concurrencia comienzan a producirse.
El código está debajo, ¿es esta la mejor manera de hacerlo?
Semaphore Lock = new Semaphore(10, 10);
List<string> folderPathList = new List<string>();
//folderPathList populated
foreach (string folderPath in folderPathList)
{
Lock.WaitOne();
new Thread(delegate()
{
WebRequest request = WebRequest.Create(folderPath);
request.Credentials = DefaultCredentials;
request.Method = "MKCOL";
WebResponse response = request.GetResponse();
response.Close();
Lock.Release();
}).Start();
}
for(int i = 1;i <= 10;i++)
{
Lock.WaitOne();
}
La excepción es algo en la línea de
Excepción no controlada: System.Net.WebException: no se puede conectar al servidor remoto ---> System.Net.Sockets.SocketException: normalmente solo se permite un uso de cada dirección de socket 192.0.0.1:81
en System.Net.Sockets.Socket.DoConnect (EndPoint endPointSnapshot, SocketAddre ss socketAddress)
en System.Net.Sockets.Socket.InternalConnect (EndPoint remoteEP)
en System.Net.ServicePoint.ConnectSocketInternal (Boolean connectFailure, Socket s4, Socket s6, Socket y socket, Dirección IP y dirección, Estado ConnectSocketState, IAsyncResult asyncResult, Int32 timeout, Excepción y excepción)
Para este tipo de tareas intensivas de IO, el modelo de programación asíncrono es muy útil. Sin embargo, es un poco difícil de usar en C #. C # ahora tiene soporte de nivel de idioma para async, puede probar la versión CTP .
Puede crear demasiadas conexiones y, por lo tanto, utilizar todos los puertos locales que puede usar. Hay un período de tiempo de espera para que un puerto se pueda reutilizar después de que lo cierre. WebRequest
oculta toda la gestión de zócalos de bajo nivel para usted, pero supongo que finalmente se queda sin puertos, o intenta (re) enlazar a un zócalo que ya se encuentra en el estado TIME_WAIT.
Debe asegurarse de leer el flujo de respuestas , incluso si no le importa la respuesta. Esto debería ayudar a no producir demasiadas conexiones persistentes.
WebResponse response = request.GetResponse();
new StreamReader(response.GetResponseStream()).ReadToEnd();
Voy a pegar alguna información relevante desde here :
Cuando se cierra una conexión, en el lado que está cerrando la conexión, la tupla 5 (Protocolo, IP local, Puerto local, IP remota, Puerto remoto) entra en un estado TIME_WAIT durante 240 segundos de forma predeterminada. En este caso, el protocolo es fijo: TCP, IP local, IP remota y PORT remoto también suelen ser fijos. Así que la variable es el puerto local. Lo que sucede es que cuando no se vincula, se utiliza un puerto en el rango 1024-5000. Así que más o menos tienes 4000 puertos. Si los usa todos en 4 minutos, lo que significa que aproximadamente hace 16 llamadas de servicio web por segundo durante 4 minutos, agotará todos los puertos. Esa es la causa de esta excepción.
Bien, ahora, ¿cómo se puede arreglar esto?
Una de las formas es aumentar el rango del puerto dinámico. El máximo de forma predeterminada es 5000. Puede configurarlo hasta 65534. HKLM / System / CurrentControlSet / Services / Tcpip / Parameters / MaxUserPort es la clave a usar.
La segunda cosa que puede hacer es que una vez que la conexión llegue a un estado TIME_WAIT puede reducir el tiempo que se encuentra en ese estado, el valor predeterminado es de 4 minutos, pero puede establecerlo en 30 segundos HKLM / System / CurrentControlSet / Services / Tcpip / Parámetros / TCPTimedWaitDelay es la clave a utilizar. Ponlo a 30 segundos
prueba esto
folderPathList.ToList().ForEach(p =>
{
ThreadPool.QueueUserWorkItem((o) =>
{
WebRequest request = WebRequest.Create(p);
request.Credentials = DefaultCredentials;
request.Method = "MKCOL";
WebResponse response = request.GetResponse();
response.Close();
});
EDITAR - enfoque diferente de la solicitud web
folderPathList.ToList().ForEach(p =>
{
ThreadPool.QueueUserWorkItem((o) =>
{
using (WebClient client = new WebClient())
{
client.Credentials = DefaultCredentials;
client.UploadString(p, "MKCOL", "");
}
});
});