El nucleo de la programacion asincrona son los objetos Task
y Task<T>
. Son compatibles con las palabras clave async
y await
.
Primero hay que reconocer si el codigo se usa para trabajos enlazados a I/O o si son CPU intensivos.
- Si el codigo “espera” algo como una BBDD o una response de un servidor, es codigo I/O. En este caso hay que usar
async
yawait
pero SIN usarTask.Run
- Si el codigo realiza un calculo costoso, es CPU intensivo. Use
async
yawait
y genere otro subproceso conTask.run
Async / Await (Operaciones I/O)
La palabra clave importante aqui es await
. Lo que hace es suspender la ejecucion del metodo actual y devolver el control hasta que está lista para seguir.
public Task Main()
{
string contenido = await LeerPaginaWebAsync("http://example.com");
}
public async Task<string> LeerPaginaWebAsync(string url)
{
using (HttpClient client = new HttpClient())
{
return await client.GetStringAsync(url);
}
}
Task.Run (Codigo CPU intensivo)
usando Task.Run()
fuerzas el invocar un hilo que no sea el hilo pincipal para no bloquearlo. Se usa para procesos intensivos de CPU y bloqueantes.
public Task Main()
{
// TODO: revisar que el codigo compile y funcione. pseudocodigo
string contenido = await Task.Run(() => LeerPaginaWebAsync("http://example.com"));
}
public async Task<string> LeerPaginaWebAsync(string url)
{
using (HttpClient client = new HttpClient())
{
return await client.GetStringAsync(url);
}
// hacer aqui una operacion extra muy CPU intensiva
}
Task.WhenAll (Esperando a que se completen varias tareas concurrentes)
Para situaciones en las que se necesiten recuperar fragmentos de datos al mismo tiempo.
public Task Main()
{
// TODO: revisar que el codigo compile y funcione. pseudocodigo
var urls = new List<string>
{
"http://example.com",
"http://example.org",
"http://example.net",
"http://example.info",
"http://example.edu",
"http://example.co",
"http://example.io",
"http://example.ai",
"http://example.biz",
"http://example.online"
}
// se inicia la lectura de todas las paginas web de manera concurrente
var tasksDeLectura(urls.Select(url => LeerPaginaWebAsync(url)).ToList());
// esperar a que todas las tareas de lectura se completen
string[] contenidos = await Task.WhenAll(tasksDeLectura);
foreach (var contenido in contenidos)
{
// hacer algo con las paginas web
}
}
public async Task<string> LeerPaginaWebAsync(string url)
{
using (var client = new HttpClient())
{
return await client.GetStringAsync(url);
}
}