2010-09-25 10 views
15

ho scritto un codice che sembra un po 'come questo:Fili e delegati - I dont comprendere appieno le loro relazioni

Thread t = new Thread(() => createSomething(dt, start, finish)); 
t.Start(); 

e funziona (a volte quasi sentire come se ci sono più thread)

pure io non usare delegati.

  1. Qual è il significato di un battistrada senza un delegato
  2. Se un delegato è necessario - quindi per favore mi dica cosa e come viene effettuata la connessione al delegato.

risposta

34

Il multi-threading è molto complesso. Stai tagliando e incollando il codice senza nemmeno imparare nulla sugli aspetti più basilari del threading: come iniziare un thread. Incollare qualcosa via web in un'interfaccia utente per correggere o modificare un controllo è una cosa. Questo è un processo completamente diverso. Devi studiare l'argomento, scrivere tutto il tuo codice e capire esattamente come funziona, altrimenti stai solo perdendo tempo con questo.

Un delegato è la versione .NET di un puntatore a funzione sicura. Tutti i thread richiedono un punto di ingresso per avviare l'esecuzione. Per definizione, quando viene creato un thread primario, viene sempre eseguito Main() come punto di ingresso. Qualsiasi thread aggiuntivo creato avrà bisogno di un punto di ingresso definito in modo esplicito: un puntatore alla funzione in cui dovrebbero iniziare l'esecuzione. Quindi i thread richiedono sempre un delegato.

I delegati vengono spesso utilizzati nella filettatura anche per altri scopi, principalmente i callback. Se vuoi che un thread riporti alcune informazioni come lo stato di completamento, una possibilità è creare una funzione di callback che il thread possa usare. Anche in questo caso il thread ha bisogno di un puntatore per essere in grado di eseguire la callback in modo che anche i delegati vengano utilizzati per questo. A differenza di un punto di ingresso questi sono opzionali, ma il concetto è lo stesso.

La relazione tra thread e delegati è che i thread secondari non possono semplicemente chiamare metodi come il thread dell'app principale, quindi è necessario un puntatore a funzione e i delegati fungono da puntatori a funzione.

Non si vede il delegato e non ne è stato creato uno perché il framework lo sta facendo per voi nel costruttore Thread. È possibile passare il metodo che si desidera utilizzare per avviare il thread e il codice framework crea un delegato che punta a questo metodo. Se si desidera utilizzare una richiamata, è necessario creare personalmente un delegato.

Questo è il codice senza espressioni lambda. SomeClass ha alcune elaborazioni che richiedono molto tempo e vengono eseguite sui thread in background. Per aiutare con questo il SomeThreadTask è stato creato e contiene il codice di processo e tutto il thread necessario per eseguirlo. Un secondo delegato viene utilizzato per un callback al termine del thread.

Il codice reale sarebbe più complicato e una classe reale non dovrebbe mai sapere come creare thread ecc. In modo da avere oggetti di gestione.

+3

Innanzitutto apprezzo la tua risposta dettagliata. Mi prenderò il mio tempo per impararlo attentamente. Informazioni sulla copia e incolla ... A volte un giocatore di football che impara il suo calcio nel neibourhood e poi perfezionato da una buona squadra è meglio di uno che è cresciuto in un club. In altre parole a volte bisogna sentire qualcosa prima di capirlo. Ad ogni modo ... mi hai aiutato e ti ringrazio per questo – Asaf

23

È sono utilizzando un delegato - questo è solo C# zucchero sintattico per:

Thread t = new Thread(new ThreadStart(() => createSomething(dt, start, finish))); 
t.Start(); 

Il compilatore è inferire dall'espressione lambda e le diverse sovraccarichi che il costruttore Thread ha, che il tuo scopo è:

  • Creare un'istanza del delegato ThreadStart.
  • Passarlo come argomento al sovraccarico del costruttore di Thread che accetta un oggetto ThreadStart.

Si potrebbe anche equivalentemente scrivere questo con la sintassi anonima-delega:

Thread t = new Thread(delegate() { createSomething(dt, start, finish); }); 
t.Start(); 

Se gli argomenti a createSomething non sono (catturati) gente del posto, si potrebbe scrivere questo senza metodi anonimi del tutto, che dovrebbe evidenziare la creazione del delegato molto più chiaramente:

private void Create() 
{ 
    createSomething(dt, start, finish))); 
} 

... 

Thread t = new Thread(new ThreadStart(Create)); //new ThreadStart is optional for the same reason 
t.Start(); 
+0

Grazie, le cose belle accadono quando si copia codice da persone intelligenti, eppure questo "zucchero" nasconde il modo "normale" da me ... Non dichiaro un delegato e sicuramente non capisco come funziona ... Quindi mi hai aiutato a capire che il mio programma funziona - perché è scritto correttamente, ma non capisco cosa succede sotto il cofano ... quello di cui ho veramente bisogno è un \ esempio per non "zucchero" per 'chiamare una funzione senza parametri' e 'chiamare una funzione con parametri' – Asaf

+1

Il lambda '() => createSomething (dt, start, finish)' equivale a 'nuovo delegato() {return createSomething (dt, start, finish); } '. Se il delegato restituisce 'void' non dovrebbe apparire il lambda:'() => {createSomething (dt, start, finish);} '? L'altra cosa è se l'uso di tale lambda è legale qui. –

+0

@Maciej Hehl: 1. Le parentesi e il punto e virgola sono facoltativi. 2. Le espressioni Lamba possono sempre sostituire i delegati anonimi. – Ani