haber escrito un rastreador de alto rendimiento en C#, lo que puedo decir con cierta autoridad que gestionan de forma explícita docenas o cientos de hilos no es el mejor camino a seguir. Se puede hacer (lo hice), pero es doloroso en extremo.
Dicho eso. . .
Si su aplicación está escrita la forma en que pienso, a continuación, cada hilo hace algo como esto:
while (!Shutdown)
{
// get next url to crawl from somewhere
// download the data from that url
// do something with the data
}
Pausa de los hilos entre descargas es bastante fácil. Sugeriría hacer dos instancias ManualResetEvent
: una para continuar y otra para apagar. Estos son static
de modo que todas las discusiones sobre orugas pueden acceder a ellos:
static ManualResetEvent ShutdownEvent = new ManualResetEvent(false);
static ManualResetEvent ContinueEvent = new ManualResetEvent(true);
A continuación, cada hilo utiliza WaitAny
en un bucle:
WaitHandle[] handles = new WaitHandle[] { ShutdownEvent, ContinueEvent };
while (true)
{
int handle = WaitHandle.WaitAny(handles); // wait for one of the events
if (handle == -1 || handle >= handles.Length)
{
throw new ApplicationException();
}
if (handles[handle] = ShutdownEvent)
break; // shutdown was signaled
if (handles[handle] == ContinueEvent)
{
// download the next page and do something with the data
}
}
Nota que cuando he definido la matriz handles
, he especificado ShutdownEvent
primero. El motivo es que si se señalan varios elementos, WaitAny
devuelve el índice más bajo que corresponde a un objeto señalado. Si la matriz se llenó en el otro orden, entonces no podrá cerrar sin hacer una pausa primero.
Ahora, si desea que los hilos se cierren, llame al ShutdownEvent.Set
. Y si desea que los hilos se detengan, llame al ContinueEvent.Reset
Cuando desee que los hilos se reanuden, llame al ContinueEvent.Set
.
Hacer una pausa en medio de una descarga es un poco más difícil. Es posible hacerlo, pero el problema es que si hace una pausa durante demasiado tiempo, el servidor podría perder tiempo. Y luego tendrá que reiniciar la descarga desde el principio o, si el servidor y su código lo admiten, reinicie la descarga desde el punto en que la dejó. Cualquiera de las dos opciones es bastante dolorosa, por lo que no sugeriría intentar detenerla en el medio de una descarga.
Debe proporcionar un poco más de información si desea algo así como una respuesta útil. ¿Qué están haciendo estos hilos? ¿Cómo comienzan? ¿En qué condiciones se deben "detener"? Sin más información, es imposible responder a esta pregunta. –
500 hilos en un proceso es un * enorme * número de hilos, especialmente si muchos de ellos duermen la mayor parte del tiempo. Mi consejo es rediseñar su arquitectura para que no use más hilos que procesadores en la máquina. Los hilos son muy "pesados" en C#; deberías estar creando el mínimo absoluto necesario para hacer el trabajo. ¿Qué estás haciendo que estás creando tantos hilos? –
Esta es una aplicación de rastreo web. Cada hilo pasa la mayor parte del tiempo esperando una respuesta de algún servidor web, todos los hilos se inician en el mismo lugar y deben pausarse cuando el usuario presiona el botón "pausa". La aplicación generalmente toma 700m-2G de memoria, y estoy de acuerdo con esto a menos que haya una mejor manera de hacerlo; incluso en 500 subprocesos, la aplicación generalmente requiere menos del 30% de una sola CPU para ejecutar –