2012-07-17 13 views
9

Dato il seguente metodo:attendono AsyncMethod() rispetto attendono attendono Task.Factory.StartNew <TResult> (AsyncMethod)

public async Task<MyObject> DoSomethingAsync() { 
    // do some work 
    await OpenSomeFileAsync(); 
    return new MyObject(); 
} 

C'è una differenza tra:

public async void SomeEventHandler(EventArgs args) { 
    var myObject = await await Task.Factory.StartNew<Task<MyObject>>(DoSomethingAsync); 
    // do something with myObject 
} 

e:

public async void SomeEventHandler(EventArgs args) { 
    var myObject = await DoSomethingAsync(); 
    // do something with myObject 
} 

Stavo pensando che la parte "fai un po 'di lavoro" di DoSomethingAsync avverrà immediatamente in una nuova attività in il primo caso, ma a dire il vero non capisco appieno come funzionano Tasks, async e await, e sono abbastanza sicuro che sto solo complicando le cose per me stesso.

EDIT:

Questa domanda nasce dalla guardando questo esempio Metro: http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782

In particolare in MainPage.xaml.cs, hanno questa:

var unused = Task.Factory.StartNew(async() => { // some work... }); 
// unused is of type Task<TResult> 

stavo cercando di rielaborarlo senza usare una funzione asincrona anonima e ho iniziato a chiedermi, perché non scrivere semplicemente un metodo asincrono e aspettarlo, invece di chiamare StartNew e passare una funzione asincrona?

+0

Perché si vuole scrivere in quel modo? L'intero punto di utilizzo delle nuove parole chiave 'async' /' await' era che non dovevi. –

+0

Sembra un brutto esempio di codice a disposizione –

+0

Ho appena dato un'occhiata a me stesso, e ... Wow. Sì, quel codice "Sample Windows SDK ufficiale" è ** davvero pessimo **! Penso che siano riusciti a perdere completamente il punto di 'async'! –

risposta

11

La maggior parte delle volte, aggiungere un altro Task non è utile, ma in alcuni casi, può essere.

La differenza è che se si è in thread UI (o qualcosa di simile) ed eseguire DoSomethingAsync() direttamente, la sua prima parte (// do some work) sarà anche eseguire sul thread dell'interfaccia utente, e così sarà le parti di continuazione del metodo (a meno che non usano ConfigureAwait()). D'altra parte, se si avvia un altro Task, la prima parte e tutte le parti successive di DoSomethingAsync() verranno eseguite su ThreadPool.

Se DoSomethingAsync() è scritto correttamente, aggiungere un altro Task non dovrebbe darti alcun vantaggio (e ti darà lo svantaggio di ulteriori spese generali), ma posso immaginare che ci siano casi in cui farà la differenza.

Inoltre, invece di utilizzare Task.Factory.StartNew() e due await s, si potrebbe scrivere:

await Task.Run(DoSomethingAsync); 
+1

Buon punto, non ho pensato alla parte prima dell'attesa ... +1 –

+0

Ottima risposta, grazie a tutti per la risposta! –

4

Sì, c'è una differenza: nel primo modulo, hai un livello extra di Attività, che non porta assolutamente nulla di utile.

La prima forma è sostanzialmente equivalente a questo:

Task<Task<MyObject>> task1 = Task.Factory.StartNew<Task<MyObject>>(DoSomethingAsync); 
Task<MyObject>> task2 = await task1; 
var myObject = await task2; 

Quindi in realtà non ha senso: si sta creando un compito che solo ... crea un altro compito.

+0

Grazie per la risposta - stavo pensando tanto.Se hai un momento potresti indirizzare la mia modifica? Sono un po 'confuso dall'approccio preso nell'esempio che stavo guardando ... –

+0

AFAICT, è un cattivo esempio –

+0

@justin, sono d'accordo con James, è un pessimo esempio ... non c'è motivo di creare un compito su un metodo asincrono, dal momento che già restituisce un'attività –

Problemi correlati