2012-07-17 13 views
9

Dado el siguiente método:esperan AsyncMethod() versus await await Task.Factory.StartNew <TResult> (AsyncMethod)

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

¿Existe una diferencia entre:

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

y:

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

Estaba pensando que la parte de "hacer algo de trabajo" de DoSomethingAsync ocurriría inmediatamente en una nueva tarea en el primer caso, pero para ser honesto, no entiendo completamente cómo funcionan las Tareas, la sincronización y la espera, y estoy bastante seguro de que estoy complicando demasiado las cosas por mí mismo.

EDIT:

Esta pregunta surgió de mirar este ejemplo Metro: http://code.msdn.microsoft.com/windowsapps/Sharing-Content-Target-App-e2689782

Específicamente en MainPage.xaml.cs, tienen la siguiente:

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

yo estaba tratando de volver a trabajar sin usar una función asíncrona anónima y comencé a preguntarme, ¿por qué no simplemente escribir un método asíncrono y esperarlo, en lugar de llamar a StartNew y entregar una función asíncrona?

+0

¿Por qué quieres que escribirlo de esa manera? El objetivo de utilizar las nuevas palabras clave 'async' /' await' era que no era necesario. –

+0

Parece un mal ejemplo de código fuera de uso –

+0

Acabo de echar un vistazo, y ... Wow. Sí, ese código de "muestra oficial de SDK de Windows" es ** realmente malo **. ¡Creo que se las han arreglado para perder completamente el punto de 'async'! –

Respuesta

11

La mayoría de las veces, agregar Task no es útil, pero en algunos casos puede ser.

La diferencia es que si estás en el hilo de interfaz de usuario (o algo similar) y ejecutar directamente DoSomethingAsync(), su primera parte (// do some work) también se ejecutará en el hilo de interfaz de usuario, y también lo harán las piezas de continuación del método (a menos ellos usan ConfigureAwait()). Por otro lado, si inicia otro Task, tanto la primera parte como las siguientes partes de DoSomethingAsync() se ejecutarán en el ThreadPool.

Si DoSomethingAsync() se escribe correctamente, añadiendo otra Task no debería darle ninguna ventaja (y le dará la desventaja de más sobrecarga), pero se puede imaginar que hay casos en que hará una diferencia.

Además, en lugar de utilizar Task.Factory.StartNew() y dos await s, se podría escribir:

await Task.Run(DoSomethingAsync); 
+1

Buen punto, no pensé en la parte antes de la espera ... +1 –

+0

Muy buena respuesta, gracias a todos por la respuesta! –

4

Sí, hay una diferencia: en la primera forma, tiene un nivel extra de Tarea, que no aporta absolutamente nada útil.

La primera forma es básicamente equivalente a esto:

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

lo tanto, no tiene mucho sentido: está creando una tarea que sólo ... crea otra tarea.

+0

Gracias por la respuesta, estaba pensando mucho.Si tiene un momento, ¿podría abordar mi edición? Estoy un poco confundido por el enfoque adoptado en el ejemplo que estaba viendo ... –

+0

AFAICT, es un mal ejemplo –

+0

@justin, estoy de acuerdo con James, es un ejemplo realmente malo ... no hay razón para crear un tarea en un método asíncrono, ya que devuelve una tarea –

Cuestiones relacionadas