Quiero utilizar métodos asincrónicos recientes de C# 5.0, pero de alguna manera específica.¿Es posible utilizar la misma firma de método asíncrono en C# 5.0 y poder decidir más adelante cómo ejecutar dicho método?
Considere ejemplo de código siguiente:
public abstract class SomeBaseProvider : ISomeProvider
{
public abstract Task<string> Process(SomeParameters parameters);
}
public class SomeConcreteProvider1 : SomeBaseProvider
{
// in this method I want to minimize any overhead to create/run Task
// NOTE: I remove here async from method signature, because basically I want to run
// method to run in sync!
public override Task<string> Process(SomeParameters parameters) {
string result = "string which I don't need any async code to get";
return Task.Run(() => result);
}
}
public class SomeConcreteProvider2 : SomeBaseProvider
{
// in this method, it's OK for me to use async/await
public async override Task<string> Process(SomeParameters parameters) {
var data = await new WebClient().DownloadDataTaskAsync(urlToRequest);
string result = // ... here we convert data byte[] to string some way
return result;
}
}
Ahora cómo voy a utilizar métodos asincrónicos (se puede ignorar hecho de que los consumidores realmente ASP.NET MVC4 aplicación en mi caso ... puede ser cualquier cosa):
public class SomeAsyncController : AsyncController
{
public async Task<ActionResult> SomethingAsync(string providerId)
{
// we just get here one of providers I define above
var provider = SomeService.GetProvider(providerId);
// we try to execute here Process method in async.
// However we might want to actually do it in sync instead, if
// provider is actually SomeConcreteProvider1 object.
string result = await provider.Process(new SomeParameters(...));
return Content(result);
}
}
Como se puede ver tengo 2 implementaciones, cada uno va a realizar de forma diferente: uno Quiero correr en asíncrono y no me cuadra hilo (SomeConcreteProvider2), mientras que otro Quiero ser capaz de ejecutar de forma sincronizada y no crea ningún objeto Task, etc. (que no puedo codificar en el código anterior, es decir, ¡Sí creo una nueva tarea aquí!).
Ya hay preguntas como How would I run an async Task<T> method synchronously?. Sin embargo, no quiero ejecutar algo en sincronización ... quiero evitar cualquier sobrecarga si sé en el momento del código (es decir, antes del tiempo de ejecución) que algunas implementaciones de métodos NO serán realmente asincrónicas y no necesitarán usar ningún hilo/I/O puertos de finalización, etc. Si comprueba el código anterior, es fácil ver que el método en SomeConcreteProvider1 básicamente construirá una cadena (html), puede hacerlo muy rápidamente en el mismo hilo de ejecución. Sin embargo, el mismo método en SomeConcreteProvider2 necesitará crear una solicitud web, obtener respuesta web y procesarla de algún modo, y quiero hacer al menos una solicitud web en Async para evitar el bloqueo de un hilo completo durante el tiempo de solicitud (puede dejarlo mucho tiempo en realidad).
Así que la pregunta es: ¿cómo organizar mi código (diferentes firmas de métodos o diferentes implementaciones, o?) Para poder decidir cómo ejecutar el método y evitar CUALQUIER sobrecarga posible que cause, por ejemplo, Task.Run (.. .) en SomeConcreteProvider1.Process method?
Actualización 1: soluciones obvias (creo que algunos de ellos durante el proceso de que se trate), como por ejemplo, para añadir una propiedad estática a cada uno de los proveedores (decir 'isAsyncImplementation') y luego verificar que la propiedad de decidir cómo para ejecutar el método (con aguardar o sin esperar en la acción del controlador) también hay algo de sobrecarga: DI si quiere algo mejor si es posible: D
P.S. fue realmente difícil crear el título correcto para esta pregunta. Estaré contento si alguien puede arreglarlo :) Gracias – Evereq
Creo que la creación de un método asíncrono sin espera puede ser más rápido debido al almacenamiento en caché de tareas. – SLaks
@SLaks ¿quiere decir que mi código en SomeConcreteProvider1.Process ya es lo suficientemente rápido debido al almacenamiento en caché de algunas tareas? – Evereq