Domanda

Ecco un compito relativamente comune per me e, penso, per molti programmatori .NET:
Voglio utilizzare .NET ThreadPool per la pianificazione di thread di lavoro che devono elaborare un determinato tipo di attività.

Come aggiornamento, le firme per il metodo di accodamento di ThreadPool e del delegato associato sono:

public static bool QueueUserWorkItem (
    WaitCallback callBack,
    Object state
)
public delegate void WaitCallback (Object state)

Pertanto, una tipica classe di thread di lavoro generici sarebbe simile a:

public class Worker<T> {
    public void schedule(T i_task) {
        ThreadPool.QueueUserWorkItem(execute, i_task)
    }
    private void execute(Object o){
        T task = (T)o;  //What happened to the type safety?  
        executeTask(task);
    }
    private void executeTask(T i_task){
        //process i_task
    }
}

Notare il tipo del parametro state ? È Object !

Qual è il motivo convincente per cui il team di .NET ha scelto di non rendere generico il metodo QueueUserWorkItem (o l'intera classe ThreadPool )? Non riesco a credere che lo abbiano semplicemente ignorato.

Ecco come mi piacerebbe vederlo:

//in the ThreadPool class:
public static bool QueueUserWorkItem<T> (
    WaitCallback<T> callBack,
    T state
)
public delegate void WaitCallback<T> (T state)

Ciò renderebbe la classe operaia sicura (e molto più chiara, IMHO):

public class Worker<T> {
    public void schedule(T i_task) {
        ThreadPool.QueueUserWorkItem<T>(execute, i_task)
    }
    private void execute(T i_task){
        //process i_task
    }
}

Mi manca qualcosa.

È stato utile?

Soluzione

Sembra che tu stia parlando di una coda di lavoro? (e sembro clippy ...)

Per la cronaca, i thread del pool di thread devono essere generalmente utilizzati per brevi lavori. Idealmente, dovresti creare i tuoi thread per una coda di lunga durata. Si noti che .NET 4.0 potrebbe adottare le librerie CCR / TPL, quindi otterremo alcune code di lavoro integrate gratuitamente, ma non è difficile scrivere una coda di lavoro con thread. E puoi anche renderlo generico ;-p

Riguardo alla domanda: preferisco che l'approccio delle variabili catturate passi lo stato nei thread (siano essi Thread , ThreadPool o Control.Invoke ):

    Thread t = new Thread(() => SomeMethod(arg));
    t.IsBackground = true;
    t.Name = "Worker n";
    t.Start();

Questo ti dà un controllo molto più granulare sul thread, senza saturare il ThreadPool .

Altri suggerimenti

Poiché è banale impacchettare qualunque stato ti piace passando un delegato anonimo o lambda al threadpool (tramite acquisizione variabile), non è necessaria una versione generica.

Ad esempio, è possibile scrivere una funzione di utilità:

static void QueueItem<T>(Action<T> action, T state)
{
    ThreadPool.QueueUserWorkItem(delegate { action(state); });
}

Ma non sarebbe terribilmente utile, dato che puoi semplicemente usare un delegato ogni volta che hai bisogno di stato nell'attività in pool.

ThreadPool esiste da .NET 1.1 che non aveva Generics.

Mi piace come hanno scelto di non rompere la compatibilità all'indietro :-)

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