Domanda

Va ??bene ... Ho dato una buona ricerca al sito e ho letto molti post su questo argomento. Ho trovato questa domanda: Codice per un semplice pool di thread in C # particolarmente utile.

Tuttavia, come sembra sempre, ciò di cui ho bisogno varia leggermente.

Ho esaminato l'esempio di MSDN e adattato un po 'alle mie esigenze. L'esempio a cui mi riferisco è qui: http: / /msdn.microsoft.com/en-us/library/3dasc8as(VS.80,printer).aspx

Il mio problema è questo. Ho un set abbastanza semplice di codice che carica una pagina web tramite le classi HttpWebRequest e WebResponse e legge i risultati tramite un Stream . Eseguo questo metodo in un thread in quanto dovrà essere eseguito più volte. Il metodo in sé è piuttosto breve, ma il numero di volte che deve essere attivato (con dati vari per ogni volta) varia. Può essere ovunque da 1 a 200.

Tutto ciò che ho letto sembra indicare che la classe ThreadPool sia la prima candidata. Ecco cosa le cose si fanno difficili. Potrei aver bisogno di spegnere questa cosa dire 100 volte, ma posso avere solo 3 thread al massimo in esecuzione (per questo particolare compito).

Ho provato a impostare il MaxThreads sul ThreadPool tramite:

ThreadPool.SetMaxThreads(3, 3);

Non sono del tutto convinto che questo approccio funzioni. Inoltre, non voglio bloccare altri siti Web o programmi in esecuzione sul sistema su cui verrà eseguito. Quindi, limitando il numero di thread sul ThreadPool , posso essere certo che ciò riguarda solo il mio codice e i miei thread?

L'esempio MSDN utilizza l'approccio drive dell'evento e chiama WaitHandle.WaitAll (doneEvents); che è come lo sto facendo.

Quindi il cuore della mia domanda è, come si può garantire o specificare un numero massimo di thread che possono essere eseguiti per il loro codice, ma il codice continua a eseguire più thread come i precedenti finiscono fino a un punto arbitrario? Sto affrontando questo nel modo giusto?

Cordiali saluti,

Jason


Va ??bene, ho aggiunto un approccio semaforo e ho rimosso completamente il codice ThreadPool . Sembra abbastanza semplice. Ho ricevuto le mie informazioni da: http://www.albahari.com/threading/part2.aspx

È questo esempio che mi ha mostrato come:

[il testo qui sotto è una copia / incolla dal sito]

Un Semaphore con una capacità di uno è simile a un Mutex o lock , tranne per il Semaphore non ha un "proprietario" & # 8211; è agnostico. Qualsiasi thread può chiamare Release su un Semaphore , mentre con Mutex e lock , solo il thread che ha ottenuto la risorsa può rilasciarlo.

Nel seguente esempio, dieci thread eseguono un ciclo con un'istruzione Sleep nel mezzo. Un Semaphore assicura che non più di tre thread possano eseguire contemporaneamente l'istruzione Sleep :

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();
        }
    }
}
È stato utile?

Soluzione

Nota: se lo stai limitando a " 3 " solo per non sopraffare la macchina che esegue la tua app, per prima cosa mi assicurerei che questo sia un problema. Il threadpool dovrebbe gestirlo per te. D'altra parte, se non vuoi sopraffare qualche altra risorsa, continua a leggere!


Non puoi gestire le dimensioni del threadpool (o davvero gran parte di esso).

In questo caso, utilizzerei un semaforo per gestire l'accesso alla tua risorsa. Nel tuo caso, la tua risorsa sta eseguendo lo scrap web o sta calcolando un rapporto, ecc.

Per fare ciò, nella tua classe statica, crea un oggetto semaforo:

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

Quindi, in ogni thread, fai questo:

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();
}

Ogni thread si bloccherà su S.WaitOne () fino a quando non viene dato il segnale per procedere. Una volta che S è stato ridotto di 3 volte, tutti i thread si bloccheranno fino a quando uno di essi incrementa il contatore.

Questa soluzione non è perfetta.


Se vuoi qualcosa di un po 'più pulito e più efficiente, ti consiglio di seguire un approccio BlockingQueue in cui accoda il lavoro che desideri venga eseguito in un oggetto globale Blocking Queue.

Nel frattempo, hai tre thread (che hai creato - non nel pool di thread), eliminando il lavoro dalla coda da eseguire. Questo non è così difficile da configurare ed è molto veloce e semplice.

Esempi:

Altri suggerimenti

È una classe statica come qualsiasi altra, il che significa che qualsiasi cosa tu faccia con essa influenza ogni altro thread nel processo corrente. Non influisce su altri processi.

Tuttavia, considero questo uno dei maggiori difetti di progettazione in .NET. Chi ha avuto la brillante idea di rendere il pool di thread statico ? Come mostra il tuo esempio, spesso vogliamo un pool di thread dedicato alla nostra attività, senza che interferisca con attività non correlate in altre parti del sistema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top