C# thread pool limiting threads


Muy bien...Le he dado al sitio una búsqueda justa y he leído muchos posts sobre este tema. Encontré esta pregunta: Código para un simple thread pool en C# especialmente útil.

Sin embargo, como siempre parece, lo que necesito varía ligeramente.

He revisado el ejemplo de MSDN y lo he adaptado a mis necesidades. El ejemplo al que me refiero está aquí: http://msdn.microsoft.com/en-us/library/3dasc8as (VS.80,impresora).aspx

Mi problema es este. Me tener un conjunto de código bastante simple que cargue una página web a través de las clases HttpWebRequest y WebResponse y lea los resultados a través de un Stream. Disparo este método en un hilo, ya que tendrá que ejecutarse muchas veces. El método en sí es bastante corto, pero el número de veces que necesita ser disparado (con datos variados para cada momento) varía. Puede ser de 1 a 200.

Todo lo que he leído parece indicar que la clase ThreadPool es el candidato principal. Esto es lo que las cosas se ponen difíciles. Podría necesitar dispara esta cosa decir 100 veces, pero solo puedo tener 3 hilos a lo sumo en ejecución (para esta tarea en particular).

He intentado establecer el {[6] } en el ThreadPool vía:

ThreadPool.SetMaxThreads(3, 3);

No estoy completamente convencido de que este enfoque esté funcionando. Además, no quiero golpear otros sitios web o programas que se ejecutan en el sistema en el que se ejecutará. Por lo tanto, al limitar el # de hilos en el ThreadPool, puedo estar seguro de que esto se refiere a mi código y mis hilos solamente?

El MSDN ejemplo utiliza el enfoque de unidad de eventos y llama WaitHandle.WaitAll(doneEvents); que es cómo estoy haciendo esto.

Entonces, el corazón de mi pregunta es, ¿cómo se asegura o especifica un número máximo de subprocesos que se pueden ejecutar para su código, pero el código sigue ejecutando más subprocesos a medida que los anteriores terminan hasta algún punto arbitrario? ¿Estoy abordando esto de la manera correcta?

Sinceramente,

Jason


Bien, he agregado un enfoque de semáforo y eliminado completamente el código ThreadPool. Parece bastante simple. Recibí mi información de: http://www.albahari.com/threading/part2.aspx

Es este ejemplo el que me mostró cómo:{[25]]}

[el texto de abajo aquí es una copia / pega del sitio]

Un Semaphore con una capacidad de uno es similar a un Mutex o lock, excepto que el Semaphore no tiene "propietario" – es independiente del hilo. Cualquier subproceso puede llamar a Release en un Semaphore, mientras que con Mutex y lock, solo el subproceso que obtuvo el recurso puede liberarlo.

En en el siguiente ejemplo, diez subprocesos ejecutan un bucle con una instrucción Sleep en el medio. Un Semaphore asegura que no más de tres subprocesos pueden ejecutar esa instrucción Sleep a la vez:

class SemaphoreTest
{
    static Semaphore s = new Semaphore(3, 3);  // Available=3; Capacity=3

    static void Main()
    {
        for (int i = 0; i < 10; i++)
            new Thread(Go).Start();
    }

    static void Go()
    {
        while (true)
        {
            s.WaitOne();

            Thread.Sleep(100);   // Only 3 threads can get here at once

            s.Release();
        }
    }
}
Author: Community, 2009-01-14

2 answers

Nota: si está limitando esto a "3" solo para no abrumar a la máquina que ejecuta su aplicación, primero me aseguraría de que esto sea un problema. Se supone que Threadpool se encargará de esto por ti. Por otro lado, si no quieres abrumar a algún otro recurso, ¡sigue leyendo!


No puedes manejar el tamaño del threadpool (o realmente mucho de nada al respecto).

En este caso, usaría un semáforo para administrar el acceso a su recurso. En su caso, el recurso se está ejecutando el raspado web, o el cálculo de algún informe, etc.

Para hacer esto, en su clase estática, cree un objeto semáforo:

System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3);

Luego, en cada hilo, haces esto:

System.Threading.Semaphore S = new System.Threading.Semaphore(3, 3);

try
{
    // wait your turn (decrement)
    S.WaitOne();
    // do your thing
}

finally {
    // release so others can go (increment)
    S.Release();
}

Cada hilo se bloqueará en la S. WaitOne() hasta que se le dé la señal para continuar. Una vez que S ha sido decrementado 3 veces, todos los hilos se bloquearán hasta que uno de ellos incremente el contador.

Esta solución no es perfecta.


Si quieres algo un poco más limpio, y más eficiente, yo recomendamos ir con un enfoque de BlockingQueue en el que encueue el trabajo que desea realizar en un objeto de Cola de bloqueo global.

Mientras tanto, tienes tres subprocesos (que creaste not no en el threadpool), sacando el trabajo de la cola para realizar. Esto no es tan difícil de configurar y es muy rápido y simple.

Ejemplos:

 29
Author: Michael Haren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:20

Es una clase estática como cualquier otra, lo que significa que cualquier cosa que hagas con ella afecta a todos los demás subprocesos en el proceso actual. No afecta a otros procesos.

Sin embargo, considero que este es uno de los defectos de diseño más grandes en.NET. ¿A quién se le ocurrió la brillante idea de hacer que el grupo de hilos sea estático? Como muestra su ejemplo, a menudo queremos un grupo de subprocesos dedicado a nuestra tarea, sin que interfiera con tareas no relacionadas en otras partes del sistema.

 0
Author: jalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-14 21:02:31