c# - net - mvc run async task
¿Cada operador ''en espera'' resultará en una máquina de estado? (3)
Por favor considere el siguiente código:
public async Task<string> GetString()
{
//Some code here...
var data = await A();
//Some more code...
return data;
}
private async Task<string> A()
{
//Some code here..
var data = await B();
//manipulating data...
return data;
}
private async Task<string> B()
{
//Some code here..
var data = await C();
//manipulating data...
return data;
}
private async Task<string> C()
{
//Some code here..
var data = await FetchFromDB();
//manipulating data...
return data;
}
private async Task<string> FetchFromDB()
{
return await SOME_HTTP_REQUEST;
}
Este código demuestra una funcionalidad más básica: métodos anync anidados. ¿Se traducirá cada método a una máquina de estados? ¿O es el compilador lo suficientemente sofisticado como para generar una estructura más eficiente? En algunos de mis proyectos, hay ~ 20 métodos entre la UI / WebAPI y la llamada de E / S: ¿eso afecta la compensación entre la sobrecarga async-await (como la máquina de estados) y los beneficios de hilos no bloqueantes? ? Quiero decir, si, por ejemplo, la sobrecarga de 4 máquinas de estado (4 métodos asíncronos anidados) equivale a 50 ms de E / S de bloqueo (en términos de intercambio), la máquina de estado 20 será igual a la demora de E / S más larga ( 250 ms)?
¿Se traducirá cada método a una máquina de estados? ¿O es el compilador lo suficientemente sofisticado como para generar una estructura más eficiente?
No, el compilador generará una máquina de estados para cada una de estas llamadas. El compilador no verifica la cadena de llamada semántica de sus métodos. Generará una máquina de estado solo por método.
Puedes ver eso claramente al mirar el código compilado:
¿eso afecta la compensación entre la sobrecarga async-await (como la máquina de estados) y los beneficios de hilos no bloqueantes?
Deberá probar su código para poder decir eso. En general, Async IO es bueno cuando necesita un rendimiento total. Si varios usuarios llaman simultáneamente a sus métodos de sincronización, podrá ver los beneficios. De lo contrario, es posible que no vea ningún efecto de ganancia de rendimiento. Nuevamente, comparta su código.
Cada método tendrá una máquina de estado, sí.
Tenga en cuenta que la "sobrecarga" de la máquina de estado es principalmente la asignación de un objeto (eso y algunos goto
s, que serán bastante rápidos), por lo que cualquier tipo de "optimización" que realice para eliminarlo es lo mismo que no crear una instancia de una clase una vez.
En cuanto a si su costo es mayor o menor que el hecho de hacer el trabajo de forma sincrónica, eso es algo que tendrá que hacer para evaluar el rendimiento dado los detalles de su aplicación y hardware para estar seguro.
await
no importa en este caso. Cada método async
generará una máquina de estado (incluso si no tiene ninguna await
en absoluto).
Puedes ver eso con este ejemplo de TryRoslyn .
Si tiene casos en los que no se necesita una máquina de estado, donde el método realmente no necesita ser async
como este, por ejemplo:
private async Task<string> D()
{
var data = await FetchFromDB();
return data;
}
Puede eliminar la palabra clave async
y la máquina de estado que viene con ella:
private Task<string> D()
{
return FetchFromDB();
}
Pero, de lo contrario, realmente necesita la máquina de estados y un método async
no puede funcionar sin ella.
Debe tener en cuenta que la sobrecarga es bastante pequeña y, por lo general, es despreciable en comparación con los recursos que se ahorran al usar async-await
. Si se da cuenta de que ese no es el caso (mediante pruebas), probablemente solo deba hacer que la operación sea sincrónica.