In C # 4.0, abbiamo Task
nello spazio dei nomi System.Threading.Tasks . Qual è la vera differenza tra Thread
e Task
. Ho fatto un programma di esempio (aiuto preso da MSDN) per il mio bene di imparare con
Parallel.Invoke Parallel.For Parallel.ForEach
ma ho molti dubbi in quanto l’idea non è così chiara.
Ho inizialmente cercato in StackOverflow per un tipo simile di domanda, ma potrebbe essere con questo titolo di domanda che non ero in grado di ottenere lo stesso. Se qualcuno conosce lo stesso tipo di domanda che viene postata qui in precedenza, fornisci gentilmente il riferimento del link.
Un compito è qualcosa che vuoi fare.
Una discussione è uno dei tanti possibili lavoratori che svolge tale compito.
Nei termini di .NET 4.0, un’attività rappresenta un’operazione asincrona. Thread (s) vengono utilizzati per completare l’operazione suddividendo il lavoro in blocchi e assegnando a thread separati.
In termini di informatica, un Task
è un futuro o una promise . (Alcune persone usano questi due termini sinonimo, alcuni li usano in modo diverso, nessuno può essere d’accordo su una definizione precisa .) Fondamentalmente, un Task
“promette” di restituirti una T
, ma non ora tesoro, sono un po ‘occupato , perché non torni più tardi?
Un Thread
è un modo per soddisfare questa promise. Ma non tutte le Task
bisogno di una Thread
nuova di zecca. (In effetti, creare un thread è spesso indesiderabile, perché farlo è molto più costoso del riutilizzo di un thread esistente dal threadpool. Più su quello in un momento.) Se il valore che si sta aspettando proviene dal filesystem o da un database o la rete, quindi non è necessario che un thread si sieda e attenda i dati quando può servire altre richieste. Invece, l’ Task
potrebbe registrare un callback per ricevere i valori quando sono pronti.
In particolare, l’ Task
non dice perché è necessario tanto tempo per restituire il valore. Potrebbe essere che ci vuole molto tempo per calcolare, o potrebbe richiedere molto tempo per andare a prendere. Solo nel primo caso Thread
una Thread
per eseguire un’attività. (In .NET, i thread sono esageratamente costosi, quindi in genere si vuole evitarli il più ansible e in realtà li si usa solo se si desidera eseguire più pesanti calcoli su più CPU.Ad esempio, in Windows, un thread pesa 12 KiByte ( Penso che, in Linux, un thread pesa appena 4 KiByte, in Erlang / BEAM anche solo 400 byte. In .NET, è 1 MiByte!)
Quando eseguiamo le cose su più thread, non è garantito che i thread siano separati tra più processori.
Task è un object leggero per la gestione di un’unità di lavoro parallelizzabile. Può essere utilizzato ogni volta che si desidera eseguire qualcosa in parallelo. Parallelo significa che il lavoro è distribuito su più processori per massimizzare la velocità di calcolo. Le attività sono ottimizzate per sfruttare i processori multicore.
L’attività fornisce le seguenti potenti funzionalità sul thread.
Aspetta un insieme di compiti, senza un costrutto di segnalazione.
Possiamo concatenare le attività insieme per eseguirle una dopo l’altra.
Stabilire una relazione genitore / figlio quando un’attività viene avviata da un’altra attività.
L’eccezione dell’attività figlio può propagarsi all’attività padre.
Cancellazione del supporto delle attività tramite l’utilizzo di token di cancellazione.
L’implementazione asincrona è facile nell’attività, utilizzando le parole chiave ‘asincrono’ e ‘aspetta’.
La cosa nuda del metallo, probabilmente non è necessario usarla, probabilmente è ansible utilizzare un’attività LongRunning
e trarre i benefici dal TPL – Task Parallel Library, incluso in .NET Framework 4 (febbraio 2002) e superiore (anche. NET Core).
Astrazione sopra i fili. Utilizza il pool di thread (a meno che non si specifichi l’operazione come operazione LongRunning
, in tal caso, viene creato un nuovo thread sotto il cofano per te).
Come suggerisce il nome: un pool di fili. Il framework .NET gestisce un numero limitato di thread per te. Perché? Perché aprire 100 thread per eseguire costose operazioni CPU su un processore con soli 8 core non è sicuramente una buona idea. Il framework manterrà questo pool per te, riutilizzando i thread (non creando / uccidendoli ad ogni operazione) ed eseguendo alcuni di essi in parallelo, in modo che la tua CPU non brucerà.
In curriculum: usa sempre le attività.
Il compito è un’astrazione, quindi è molto più facile da usare. Ti consiglio di provare sempre ad usare le attività e se incontri qualche problema che ti rende necessario gestire un thread da solo (probabilmente l’1% delle volte), allora usa i thread.
LongRunning
( o thread se necessario ). Perché l’utilizzo delle attività porterebbe a un pool di thread con alcuni thread occupati e molte altre attività che attendono il turno per prendere il pool. Puoi usare Task
per specificare cosa vuoi fare, quindi albind Task
con una Thread
. in modo che Task
venga eseguita in Thread
appena creato anziché nel thread GUI.
Utilizzare Task
con TaskFactory.StartNew(Action action)
. Qui esegui un delegato, quindi se non utilizzi alcun thread verrebbe eseguito nello stesso thread (thread della GUI). Se si menziona una discussione è ansible eseguire questa Task
in una discussione diversa. Questo è un lavoro non necessario perché è ansible eseguire direttamente il delegato o albind quel delegato a un thread ed eseguire quel delegato in quel thread. Quindi non usarlo. è solo inutile. Se intendi ottimizzare il tuo software, questo è un buon candidato da rimuovere.
** Si prega di notare che l’ Action
è un delegate
.
Oltre ai punti di cui sopra, sarebbe bene sapere che:
L’attività è come un’operazione che si desidera eseguire, Thread aiuta a gestire tali operazioni attraverso più nodes di processo. task è un’opzione leggera poiché Threading può portare a una gestione complessa del codice
Suggerirò di leggere sempre da MSDN (Best in world)
Compito
Filo
Di solito uso Task
per interagire con Winforms e un semplice background worker per non congelare l’interfaccia utente. qui un esempio quando preferisco usare Task
private async void buttonDownload_Click(object sender, EventArgs e) { buttonDownload.Enabled = false; await Task.Run(() => { using (var client = new WebClient()) { client.DownloadFile("http://example.com/file.mpeg", "file.mpeg"); } }) buttonDownload.Enabled = true; }
VS
private void buttonDownload_Click(object sender, EventArgs e) { buttonDownload.Enabled = false; Thread t = new Thread(() => { using (var client = new WebClient()) { client.DownloadFile("http://example.com/file.mpeg", "file.mpeg"); } this.Invoke((MethodInvoker)delegate() { btnDownloadAccelerator.Enabled = true; }); }); t.IsBackground = true; t.Start(); }
la differenza è che non è necessario utilizzare MethodInvoker
e codice più breve.