c# - understanding - ¿Cómo uso await/async con el código síncrono?
task.run async c# (2)
Esa es la solución correcta.
Si quieres usar asincronismo, debes asegurarte de que sincronizas todo el camino hacia abajo. En otras palabras, si no tiene una versión asincrónica del método de llamada, debe envolverlo utilizando la tarea usted mismo.
Estoy intentando usar await / async para hacer que un código síncrono sea asíncrono. Por ejemplo, esto funciona y desbloquea el hilo de UI:
private async void button1_Click(object sender, EventArgs e)
{
var task = DoRequestAsync();
textBox1.Text = "starting async task";
var text = await task;
textBox1.Text = text;
}
private async Task<string> DoRequestAsync()
{
try
{
var client = new HttpClient();
client.Timeout = new TimeSpan(0, 0, 0, 5);
await client.GetAsync("http://123.123.123.123"); // force a timeout exception
}
catch (Exception e)
{
}
return "done!";
}
Pero esto no es así, y colgará el hilo de UI:
private async void button1_Click(object sender, EventArgs e)
{
var task = DoRequestAsync();
textBox1.Text = "starting async task";
var text = await task;
textBox1.Text = text;
}
private async Task<string> DoRequestAsync()
{
try
{
var request = WebRequest.Create("http://123.123.123.123");
request.Timeout = 5000;
request.GetResponse(); // force a timeout exception
}
catch (Exception e)
{
}
return "done!";
}
Estoy tratando de entender por qué este es el caso. Tenía la impresión de que var task = DoRequestAsync()
creará un nuevo hilo y ejecutará todo en el método de forma asíncrona, pero parece que no es el caso.
Puedo usar esto para que funcione:
await Task.Run(() => {
var request = WebRequest.Create("http://123.123.123.123");
request.Timeout = 5000;
request.GetResponse();
});
Pero esto parece un poco hacky y no estoy seguro si es la solución correcta para este problema. ¿Alguien sabe cómo puedo ejecutar un montón de código sincrónico de manera asíncrona utilizando tareas y async / await?
Esa es la solución correcta. WebRequest.GetResponse
no es un método asíncrono, por lo tanto, no devuelve una Tarea. No puede ejecutarse de forma asincrónica.
En realidad, lo que tienes allí es la solución más correcta y abreviada que puedes obtener (con Task.Run
).
Tenía la impresión de que var task = DoRequestAsync () creará un nuevo hilo y ejecutará todo en el método de forma asíncrona, pero parece que no es el caso.
No es magia. Para que se ejecute de forma asíncrona, se debe crear una nueva Tarea (no hilo) en su método asíncrono o debe esperar en uno o más métodos que devuelven Task
, Task<T>
o void
(esto es para manejadores de eventos) .
Su última declaración en el método return "done!";
simplemente devuelve una Task<string>
con el resultado "hecho".
Como nota al margen, esta es la razón por la cual HttpClient se está convirtiendo en la clase de facto de las solicitudes HTTP, especialmente para interoperar con API web, pero también para GETs / POSTs / etc. de propósito general: tiene soporte asíncrono .
Las tareas también tienen soporte para ajustar las funciones Begin * / End * (conforme al antiguo modelo de programación asincrónico - APM ). También puedes hacer:
try
{
var request = WebRequest.Create("http://123.123.123.123");
request.Timeout = 5000;
await Task.Factory.FromAsync(request.BeginGetResponse(), request.EndGetResponse, null); // force a timeout exception
}
catch (Exception e)
{
//TODO handle exception here
}