2012-09-14 14 views
5

Para ejecutar el código de forma asíncrona (por ejemplo, con async/await) Necesito una tarea adecuada. Por supuesto, hay varios métodos predefinidos en el marco que cubren las operaciones más frecuentes, pero a veces quiero escribir los propios. Soy nuevo en C#, así que es bastante posible que lo esté haciendo mal, pero al menos no estoy del todo contento con mi práctica actual. Véase el siguiente ejemplo de lo que estoy haciendo:Cómo escribir correctamente un método personalizado de devolución de tareas

public async Task<bool> doHeavyWork() 
    { 
     var b1 = await this.Foo(); 
     //var b2 = await Task<bool>.Factory.StartNew(Bar); //using Task.Run 
     var b2 = await Task.Run(()=>Bar()); 
     return b1 & b2; 
    } 

public Task<bool> Foo() 
    { 
     return Task.Factory.StartNew(() => 
            { 
             //do a lot of work without awaiting 
             //any other Task 
             return false; 
            }); 
    } 

public bool Bar() 
    { 
     //do a lot of work without awaiting any other task 
     return false; 
    } 

En general puedo crear y consumir tales métodos como el ejemplo de Foo, pero hay una lambda 'extra' que contiene toda la lógica del método que no parece muy bonito yo. Otra opción es consumir cualquier Método como el ejemplo de Bar, sin embargo, creo que es aún peor porque no está claro que este método deba ejecutarse de forma asíncrona (aparte de los nombres de métodos adecuados, como BarAsync) y Task.Factory.StartNew puede tener que repetirse varias veces en el programa. No sé cómo decirle al compilador que este método devuelve una Tarea, envuélvala como un todo en una Tarea cuando se la llame, que es lo que quiero hacer.

Finalmente mi pregunta: ¿Cuál es la mejor manera de escribir este método? ¿Puedo deshacerme de la lambda 'extra' (sin agregar un método adicional nombrado, por supuesto)?

EDIT Como dijo Servy siempre hay buenas razones para tener una versión síncrona del método. Se debe proporcionar una versión asíncrona solo si es absolutamente necesario (enlace de Stephen Cleary).

+0

'" sin agregar un método adicional nombrado por supuesto "' ¿por qué rechazar eso como una opción? Crea 'public bool Bar' y' public Task BarAsync'. – Servy

+0

Quería evitar la sobrecarga. Si tiene sentido utilizar un método sincrónico o asíncrono, estará bien. Si no, habría una BarAsync pública y una Barra privada (para ocultarla) y en este caso no veo muchas razones para ello. – marce

Respuesta

3

¿Se acabaría el mundo si alguien quisiera llamar al Bar sin iniciarlo en un nuevo hilo/Tarea? ¿Qué pasa si hay otro método que ya está en un hilo de fondo por lo que no es necesario iniciar una nueva tarea para simplemente ejecutar ese código de larga ejecución? ¿Qué pasa si el método termina siendo refactorizado en una biblioteca de clases que se llama tanto desde el contexto de la aplicación de escritorio como desde un contexto de consola o ASP? En esos otros contextos, ese método probablemente solo necesite ejecutarse directamente, no como un Task.

Diría que su código debe parecerse a Bar, a menos que sea absolutamente imperativo que, bajo ninguna circunstancia, se ejecute ese código sin iniciar un nuevo Task.

También tenga en cuenta que con las versiones más recientes de .NET debería pasar de Task.Factory.StartNew a Task.Run, por lo que la cantidad de código debería bajar (un poco).

+1

Bien, entiendo tu punto. Así que no hay ninguna función de 'forzar este método en una tarea' porque generalmente es una mala idea :) Y gracias por la sugerencia de Run. Task, de alguna manera lo extrañé ... – marce

+3

También vea: [¿Debería exponer los empaquetadores asíncronos para los métodos sincrónicos? ] (http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx) –

Cuestiones relacionadas