2013-07-02 13 views
19

Proprio ora sto usando il seguente codice per aggiungere thread in coda. Non mi piace. E i miei colleghi non lo faranno perché non conoscono molto bene C#. Tutto quello che voglio è ovviamente mettere in coda un metodo per essere eseguito in una nuova discussione.C# - ThreadPool QueueUserWorkItem Utilizzare?

private static void doStuff(string parameter) 
{ 
    // does stuff 
} 

// call (a) 
ThreadPool.QueueUserWorkItem(a => doStuff("hello world")); 
// call (b) 
ThreadPool.QueueUserWorkItem(delegate { doStuff("hello world"); }); 

Quindi ci sono altre varianti di utilizzo di ThreadPool.QueueUserWorkItem?

Il migliore sarebbe un altro 1-Line-Call. Se possibile con l'uso di Func<> o Action<>.


MODIFICA: Ottenuto (b) dalle risposte e dai commenti e mi piace già di più.

+2

Cosa c'è di sbagliato in ThreadPool.QueueUserWorkItem() nello scenario? –

+1

potresti usare la parola chiave "delegato". Qualcosa di simile, ThreadPool.QueueUserWorkItem (delegate {doStuff ("");}). Proprio come lo stesso metodo sopra, ma come desideri, questo è solo un altro modo di farlo ... –

+1

Perché in tutto il mondo pensi che la sintassi dei delegati sia più pulita di lambda !? –

risposta

12

La risposta alla domanda dipende da come si progetta l'applicazione. Lo metti in un progetto comune? non vuoi sovraccaricare una semplice operazione.

Tuttavia, è possibile creare una chiamata generica per ThreadPool QueueUserItem che riceve parametri, 1 parametro, 2 parametro, ecc. Questo è buono invece di inviare una stringa semplice e di essere limitato.

Questo come si IMPL una parametri QueueUserItem con WaitCallback:

ThreadPool.QueueUserWorkItem(
    new WaitCallback(delegate(object state) 
    { YourMethod(Param1, Param2, Param3); }), null); 

tratto da C# Execute Method (with Parameters) with ThreadPool

E alcuni link per le idee:
http://msdn.microsoft.com/en-us/library/4yd16hza.aspx
Generic ThreadPool in .NET
Difference between delegate.BeginInvoke and using ThreadPool threads in C#

+0

Ciò sarebbe possibile anche con 'Func' o' Action' o senza il corpo della chiamata in più? – Bitterblue

+0

Sarà possibile, quando si crea WaitCallback, non inviare un semplice "delegato", inviare invece il proprio delegato. * ma *, come prevedi di ottenere il risultato? di solito quando si invia un'operazione al thread di lavoro, non ci si aspetta di ottenere un risultato, solo per assicurarsi che il lavoro sia completato. È possibile ottenere questo implementando un modello asincrono. http://www.c-sharpcorner.com/UploadFile/rmcochran/multithreadasyncwebservice05262007094719AM/multithreadasyncwebservice.aspx – ilansch

13

Non sono del tutto sicuro del tipo di sintassi che stai cercando, ma se non ti piace il a inutilizzato nel tuo esempio, perché non usare invece Task?

Task.Run(() => doStuff("hello world")); 

Non sembra molto meglio, ma almeno non ha un identificatore inutilizzato.

Nota: Task.Run() è .Net 4.5 o successivo. Se stai usando .Net 4 devi fare:

Task.Factory.StartNew(() => doStuff("hello world")); 

che non è così breve.

Entrambe utilizzano il pool di thread.

Se davvero si deve evitare di utilizzare un lambda, è possibile utilizzare un delegato anonimo (che @nowhewhomustnotbenamed già accennato):

Task.Run(delegate { doStuff("Hello, World!"); }); 

Ma qual è il punto di che? È molto meno leggibile!

+0

In realtà voglio evitare la cosa Lambda. – Bitterblue

+0

@ mini-me Bene, ho aggiunto un esempio che evita di usare un lambda ... È peggio di così, IMO. –

+9

@ mini-me Le espressioni Lambda hanno praticamente sostituito i delegati anonimi un po 'di tempo fa. Quindi faresti bene ad abituarti a loro più presto che dopo. – nashwan

2

Che dire di questo ?

class Program 
{ 
    static void Main(string[] args) 
    { 
     ThreadPool.QueueUserWorkItem(MyWork, "text"); 
     Console.ReadKey(); 
    } 

    private static void MyWork(object argument) 
    { 
     Console.WriteLine("Argument: " + argument); 
    } 
} 

Oppure, se non si vuole essere la firma restrittive e hanno un modo semplice di mettere metodi su un thread si può fare come this.For metodi che fare e non restituiscono un valore e avere fino a 6 i parametri ti richiederebbe di definire 12 sovraccarichi se non sbaglio.Richiede un po 'più di lavoro in anticipo, ma è più semplice da usare.

class Program 
{ 
    static void Main(string[] args) 
    { 
     var myClass = new MyClass(); 
     myClass.DoWork(); 
     Console.ReadKey(); 
    } 
} 

public static class ObjectThreadExtension 
{ 
    public static void OnThread(this object @object, Action action) 
    { 
     ThreadPool.QueueUserWorkItem(state => 
     { 
      action(); 
     }); 
    } 

    public static void OnThread<T>(this object @object, Action<T> action, T argument) 
    { 
     ThreadPool.QueueUserWorkItem(state => 
     { 
      action(argument); 
     }); 
    } 
} 

public class MyClass 
{ 
    private void MyMethod() 
    { 
     Console.WriteLine("I could have been put on a thread if you like."); 
    } 

    private void MySecondMethod(string argument) 
    { 
     Console.WriteLine(argument); 
    } 

    public void DoWork() 
    { 
     this.OnThread(MyMethod); 
     this.OnThread(MySecondMethod, "My argument"); 
    } 
} 
+0

Questo sarebbe un vincitore per me, se non fosse la restrizione della firma come quella. Ma è ancora bello dargli un metodo e averne a che fare. – Bitterblue

+0

@Bitterblue Ho aggiunto un secondo approccio. Un po 'più di lavoro in anticipo, ma più facile da usare a mio parere. –

Problemi correlati