2012-05-02 18 views
32

Sto cercando di capire lo scopo di TaskCompletionSource e la sua relazione con il lavoro asincrono/senza thread. Penso di avere l'idea generale, ma voglio assicurarmi che la mia comprensione sia corretta.TaskCompletionSource - Tentativo di comprendere il lavoro asincrono senza thread

Ho iniziato a esaminare la libreria parallela task (TPL) per capire se c'era un buon modo per creare il proprio lavoro threadless/asincrono (ad esempio, stai cercando di migliorare la scalabilità del tuo sito ASP.NET) più la comprensione del TPL sembra essere molto importante in futuro (async/await). Il che mi ha portato allo TaskCompletionSource.

Dal mio punto di vista sembra che l'aggiunta di TaskCompletionSource a una delle tue classi non faccia molto in quanto rende la codifica asincrona; se stai ancora eseguendo il codice di sincronizzazione, la chiamata al tuo codice verrà bloccata. Penso che questo sia vero anche per le API di Microsoft. Ad esempio, ad esempio in DownloadStringTaskAsync fuori dalla classe WebClient, qualsiasi codice di impostazione/sincronizzazione che stanno inizialmente bloccerà. Il codice che stai eseguendo deve essere eseguito su alcuni thread, o il thread corrente o dovrai eseguirne uno nuovo.

Quindi si utilizza TaskCompletionSource nel proprio codice quando si chiamano altre chiamate async da Microsoft in modo che il client delle classi non debba creare un nuovo thread per la classe da non bloccare.

Non sono sicuro di come Microsoft esegua internamente le proprie API asincrone. Ad esempio, è disponibile un nuovo metodosu SqlDataReader per .Net 4.5. So che ci sono IO Completion Ports. Penso che sia un'astrazione di livello inferiore (C++?) Che probabilmente la maggior parte degli sviluppatori di C# non useranno. Non sono sicuro se le porte di completamento dell'IO funzioneranno per il database o le chiamate di rete (HTTP) o se sono utilizzate solo per il file IO.

Quindi la domanda è, ho ragione nella mia comprensione corretta? Ci sono alcune cose che ho rappresentato in modo errato?

+0

qual è la domanda? –

+0

Se la mia comprensione è corretta ... non sono sicuro se lo sia o no – coding4fun

risposta

53

TaskCompletionSource viene utilizzato per creare oggetti Task che non eseguono codice.

Sono utilizzati un po 'dalle nuove API asincrone di Microsoft - ogni volta che ci sono operazioni asincrone basate su I/O (o altre operazioni asincrone basate su CPU, come un timeout). Inoltre, qualsiasi metodo async Task verrà utilizzato TCS per completare il suo restituito Task.

Ho un post sul blog Creating Tasks che discute diversi modi per creare istanze Task. È scritto da una prospettiva async/await (non una prospettiva TPL), ma si applica ancora qui.

vedere anche eccellenti messaggi di Stephen Toub:

+0

Grazie Stephen ma la mia comprensione degli interni è corretta? – coding4fun

+1

Qualsiasi metodo asincrono (ovviamente) ha una parte sincrona che viene utilizzata per avviare l'operazione asincrona. IIRC, IOCP può essere usato per qualsiasi tipo di trasferimento di dati basato su HANDLE', e non è raro (oggi) avere un'operazione IOCP avvolta in un 'Begin' /' End' avvolto in un metodo 'async' che lo avvolge in un 'Task' (usando' TaskCompletionSource'). –

+0

Sto anche cercando di capire l'utilizzo di TaskCompletionSource, e sono un po 'confuso sul motivo per cui avresti un'attività che non esegue codice. Ho letto il tuo post sul blog; sembra che TCS sia usato come un evento a cui un chiamante può iscriversi, ma perché vorresti farlo quando puoi utilizzare una normale attività e attendere l'attività fino al suo completamento? –

4

Mi piace la spiegazione che è stata fornita in http://tutorials.csharp-online.net/TaskCompletionSource

(mi dispiace, il collegamento potrebbe essere morto per il momento)

primi due paragrafi sono al di sotto

Abbiamo visto come Task.Run crea un'attività che esegue un delegato su un thread in pool (o non in pool). Un altro modo per creare un'attività è con TaskCompletionSource.

TaskCompletionSource consente di creare un'attività da qualsiasi operazione che avvia e termina dopo qualche tempo. Funziona dando un'attività "slave" che si guida manualmente, indicando quando l'operazione termina con o errori. Questo è l'ideale per il lavoro con I/O: ottieni tutti i vantaggi di attività (con la loro capacità di propagare valori di ritorno, eccezioni, e continuazioni) senza bloccare un thread per la durata dell'operazione .

Per utilizzare TaskCompletionSource, è sufficiente creare un'istanza della classe. È espone una proprietà Task che restituisce un'attività su cui è possibile attendere e allegare continuazioni, proprio come con qualsiasi altra attività. Il compito, tuttavia, è controllato interamente dall'oggetto TaskCompletionSource tramite i seguenti metodi:

public class TaskCompletionSource<TResult> 
{ 
public void SetResult(TResult result); 
public void SetException (Exception exception); 

public void SetCanceled(); 
public bool TrySetResult (TResult result); 
public bool TrySetException (Exception exception); 
public bool TrySetCanceled(); 
... 
} 

Calling uno di questi metodi segnala il compito, mettendolo in un completata, guasto, o annullato stato (copriremo la seconda nella sezione "Cancellazione" di ). Dovresti chiamare uno di questi metodi esattamente una volta: se chiamato di nuovo, SetResult, SetException o SetCanceled genererà un'eccezione, mentre i metodi Try * restituiranno false.

L'esempio seguente stampa 42 dopo aver atteso cinque secondi:

var tcs = new TaskCompletionSource<int>(); 
new Thread (() =>  { 
         Thread.Sleep (5000); 
         tcs.SetResult (42); 
         })  
      .Start(); 
Task<int> task = tcs.Task; // Our "slave" task. 
Console.WriteLine(task.Result); // 42 

Altri citazioni interessanti

Il vero potere di TaskCompletionSource è nel creare compiti che non fanno legare le discussioni .

.. e successivamente

L'uso di TaskCompletionSource senza filo significa che un thread viene inserita solo quando la continuazione inizia, cinque secondi dopo. Siamo in grado di dimostrare questo avviando 10.000 di queste operazioni in una volta senza errore o una risorsa consumo eccessivo:

+0

Il link è morto. –

+1

Bella spiegazione – Ricky

Problemi correlati