Según tengo entendido, una de las principales cosas que hacer asyncyawait hacer es hacer que el código sea fácil de escribir y leer, pero ¿es igual usarlos para generar hilos de fondo para realizar una lógica de larga duración?
Actualmente estoy probando el ejemplo más básico. He agregado algunos comentarios en línea. ¿Me lo puedes aclarar?
// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
Task<int> access = DoSomethingAsync();
// task independent stuff here
// this line is reached after the 5 seconds sleep from
// DoSomethingAsync() method. Shouldn't it be reached immediately?
int a = 1;
// from my understanding the waiting should be done here.
int x = await access;
}
async Task<int> DoSomethingAsync()
{
// is this executed on a background thread?
System.Threading.Thread.Sleep(5000);
return 1;
}
c#
.net
asynchronous
async-await
Dan Dinu
fuente
fuente

Respuestas:
Cuando se usa
asyncyawaitel compilador genera una máquina de estado en segundo plano.Aquí hay un ejemplo en el que espero poder explicar algunos de los detalles de alto nivel que están sucediendo:
Bien, entonces, ¿qué pasa aquí?
Task<int> longRunningTask = LongRunningOperationAsync();comienza a ejecutarseLongRunningOperationSe realiza un trabajo independiente en supongamos que
await longRunningTaskse alcanza el subproceso principal (ID del subproceso = 1) .Ahora, si el
longRunningTaskno ha terminado y todavía se está ejecutando,MyMethodAsync()volverá a su método de llamada, por lo que el hilo principal no se bloqueará. CuandolongRunningTaskfinalice, un hilo del ThreadPool (puede ser cualquier hilo) volverá aMyMethodAsync()su contexto anterior y continuará la ejecución (en este caso, imprimirá el resultado en la consola).Un segundo caso sería que
longRunningTaskya ha finalizado su ejecución y el resultado está disponible. Al llegar a laawait longRunningTaskya tenemos el resultado, por lo que el código continuará ejecutándose en el mismo hilo. (en este caso, imprimir el resultado a la consola). Por supuesto, este no es el caso para el ejemplo anterior, donde hay unTask.Delay(1000)involucrado.fuente
Deben hacer que el código asincrónico sea fácil de escribir y leer, sí.
De ningún modo.
La
asyncpalabra clave habilita laawaitpalabra clave. Por lo tanto, cualquier método que useawaitdebe estar marcadoasync.No, porque los
asyncmétodos no se ejecutan en otro subproceso de forma predeterminada.No.
Puede encontrar mi
async/awaitintroducción útil. Los documentos oficiales de MSDN también son inusualmente buenos (particularmente la sección TAP ), y elasyncequipo publicó una excelente pregunta frecuente .fuente
asyncmétodos no se ejecutan en otro hilo de manera predeterminada. En su ejemplo, laSleep()llamada dentroDoSomethingAsync()bloquea el hilo actual que impide que la ejecución continúe dentrobutton1_Click()hasta que seDoSomethingAsync()complete. Tenga en cuenta que mientrasThread.Sleep()bloquea el hilo de ejecución,Task.Delay() does not.Explicación
Aquí hay un ejemplo rápido de
async/awaita un alto nivel. Hay muchos más detalles para considerar más allá de esto.Nota:
Task.Delay(1000)simula hacer trabajo durante 1 segundo. Creo que es mejor pensar en esto como esperar una respuesta de un recurso externo. Como nuestro código está esperando una respuesta, el sistema puede dejar de lado la tarea en ejecución y volver a ella una vez que haya terminado. Mientras tanto, puede hacer otro trabajo en ese hilo.En el siguiente ejemplo, el primer bloque está haciendo exactamente eso. Comienza todas las tareas inmediatamente (las
Task.Delaylíneas) y las pone a un lado. El código se detendrá en laawait alínea hasta que se haya realizado el retraso de 1 segundo antes de pasar a la siguiente línea. Dado queb,c,d, yetodo empezó ejecutar casi en el mismo momento exacto en quea(debido a la falta de la Await), deben terminar más o menos al mismo tiempo en este caso.En el siguiente ejemplo, el segundo bloque está iniciando una tarea y esperando a que termine (eso es lo que
awaithace) antes de comenzar las tareas posteriores. Cada iteración de esto lleva 1 segundo. Elawaitestá pausando el programa y esperando el resultado antes de continuar. Esta es la principal diferencia entre el primer y el segundo bloque.Ejemplo
SALIDA:
Información adicional sobre SynchronizationContext
Nota: Aquí es donde las cosas se ponen un poco confusas para mí, así que si me equivoco en algo, corríjame y actualizaré la respuesta. Es importante tener una comprensión básica de cómo funciona esto, pero puede sobrevivir sin ser un experto en él, siempre que nunca lo use
ConfigureAwait(false), aunque supongo que probablemente perderá alguna oportunidad de optimización.Hay un aspecto de esto que hace que el concepto
async/ seaawaitalgo más difícil de entender. Ese es el hecho de que en este ejemplo, todo esto está sucediendo en el mismo hilo (o al menos lo que parece ser el mismo hilo en lo que respecta a suSynchronizationContext). Por defecto,awaitrestaurará el contexto de sincronización del hilo original en el que se estaba ejecutando. Por ejemplo, en ASP.NET tiene un elementoHttpContextque está vinculado a un hilo cuando entra una solicitud. Este contexto contiene elementos específicos de la solicitud Http original, como el objeto Solicitud original que tiene elementos como idioma, dirección IP, encabezados, etc. Si cambia los hilos a la mitad del procesamiento de algo, podría terminar tratando de extraer información de este objeto en otroHttpContextque podría ser desastroso Si sabe que no usará el contexto para nada, puede optar por "no importarle". Básicamente, esto permite que su código se ejecute en un hilo separado sin traer el contexto.¿Cómo lo logras? De manera predeterminada, el
await a;código en realidad supone que DESEA capturar y restaurar el contexto:Si desea permitir que el código principal continúe en un nuevo hilo sin el contexto original, simplemente use falso en lugar de verdadero para que sepa que no necesita restaurar el contexto.
Una vez que el programa termina de pausarse, continuará potencialmente en un hilo completamente diferente con un contexto diferente. Aquí es de donde vendría la mejora del rendimiento: podría continuar en cualquier subproceso disponible sin tener que restaurar el contexto original con el que comenzó.
¿Es esto algo confuso? ¡Demonios si! ¿Puedes resolverlo? ¡Probablemente! Una vez que tenga una idea de los conceptos, continúe con las explicaciones de Stephen Cleary, que tienden a orientarse más hacia alguien con una comprensión técnica de
async/awaitya.fuente
await MethodCall()es un desperdicio absoluto? También podrías soltar elawait/async?await, creo que libera el hilo de nuevo al grupo en lugar de retenerlo. Esto lo hace disponible para su uso en otros lugares mientras espera el regreso de la TareaAdemás de las otras respuestas, eche un vistazo a wait (referencia de C #)
y más específicamente en el ejemplo incluido, explica un poco su situación
fuente
Task.Delaydispare el temporizador .Mostrando las explicaciones anteriores en acción en un programa de consola simple:
Y la salida es:
Así,
TestAsyncAwaitMethods. Eso regresa inmediatamente sin detener el hilo actual e inmediatamente vemos el mensaje 'Presione cualquier tecla para salir'LongRunningMethodestá ejecutando en segundo plano. Una vez completado, otro hilo de Threadpool recoge este contexto y muestra el mensaje finalPor lo tanto, no se bloquea el hilo.
fuente
return 1parte merece una explicación adicional: laawaitpalabra clave le permite devolver el tipo subyacente de formaTask<T>directa, lo que facilita la adaptación del código existente al mundo de espera / asíncrono . Pero no tiene que devolver un valor, ya que es posible devolver unTasksin especificar un tipo de retorno, que sería el equivalente de unvoidmétodo sincrónico . Tenga en cuenta que C # permiteasync voidmétodos, pero debe evitar hacerlo a menos que esté abordando controladores de eventos.Creo que has elegido un mal ejemplo con
System.Threading.Thread.SleepEl punto de una
asynctarea es dejar que se ejecute en segundo plano sin bloquear el hilo principal, como hacer unDownloadFileAsyncSystem.Threading.Thread.Sleepno es algo que se está "haciendo", simplemente duerme y, por lo tanto, se llega a su siguiente línea después de 5 segundos ...Lea este artículo, creo que es una gran explicación
asyncyawaitconcepto: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspxfuente
Thread.Sleepbloquea el hilo (el hilo no puede hacer nada más que permanecer inactivo), pero un método asíncrono no. En el caso deDownloadFileAsync, el hilo puede ir y hacer otra cosa hasta que llegue una respuesta del servidor remoto. Un mejor marcador de posición para "alguna tarea que lleva tiempo" en un método asíncrono esTask.Delay, ya que en realidad es asíncrono.asyncpalabra clave. Pero su método todavía se ejecutaba sincrónicamente, y esta respuesta explicaba perfectamente por qué: porque en realidad no ejecutaba ningún código asincrónico. Los métodos marcadosasyncsiguen ejecutándose sincrónicamente hasta que estéawaitincompletoTask. Si no hayawait, entonces el método se ejecuta sincrónicamente y el compilador le advertirá de eso.Aquí hay un programa de consola rápido para dejar en claro a los que siguen. El
TaskToDométodo es su método de larga ejecución que desea hacer asíncrono. Hacer que se ejecute de forma asincrónica se realiza mediante elTestAsyncmétodo. El método de bucles de prueba solo ejecuta lasTaskToDotareas y las ejecuta de forma asíncrona. Puede ver eso en los resultados porque no se completan en el mismo orden de ejecución a ejecución: informan al hilo de la interfaz de usuario de la consola cuando se completan. Simplista, pero creo que los ejemplos simplistas resaltan el núcleo del patrón mejor que los ejemplos más involucrados:fuente
Para un aprendizaje más rápido ...
Comprender el flujo de ejecución del método (con un diagrama): 3 minutos
Pregunta introspección (aprendizaje): 1 min.
Pasar rápidamente la sintaxis de azúcar: 5 minutos
Comparta la confusión de un desarrollador: 5 minutos
Problema: cambie rápidamente una implementación real del código normal a código asíncrono: 2 minutos
¿A dónde seguir?
Comprender el flujo de ejecución del método (con un diagrama): 3 minutos
En esta imagen, solo concéntrate en el n. ° 6 (nada más)
En el paso n. ° 6: la ejecución se detuvo aquí porque se ha quedado sin trabajo. Para continuar necesita un resultado de getStringTask (una especie de función). Por lo tanto, utiliza un
awaitoperador para suspender su progreso y devolver el control (rendimiento) a la persona que llama (de este método en el que estamos). La llamada real a getStringTask se realizó anteriormente en el n. ° 2. En el n. ° 2 se hizo una promesa de devolver un resultado de cadena. ¿Pero cuándo devolverá el resultado? ¿Deberíamos (# 1: AccessTheWebAsync) hacer una segunda llamada nuevamente? Quién obtiene el resultado, # 2 (declaración de llamada) o # 6 (declaración de espera)El llamador externo de AccessTheWebAsync () también está esperando ahora. Entonces, la persona que llama esperando AccessTheWebAsync, y AccessTheWebAsync está esperando GetStringAsync en este momento. Lo interesante es que AccessTheWebAsync trabajó un poco antes de esperar (# 4) quizás para ahorrar tiempo de espera. ¡La misma libertad para realizar múltiples tareas también está disponible para la persona que llama externa (y para todas las personas que llaman en la cadena) y esta es la mayor ventaja de esta cosa 'asincrónica'! Sientes que es sincrónico ... o normal, pero no lo es.
Recuerde, el método ya fue devuelto (# 2), no puede regresar nuevamente (sin segunda vez). Entonces, ¿cómo sabrá la persona que llama? ¡Se trata de tareas! La tarea fue aprobada. Se esperaba la tarea (sin método, sin valor). El valor se establecerá en la tarea. El estado de la tarea se configurará para completar. La persona que llama solo monitorea la Tarea (# 6). Entonces 6 # es la respuesta a dónde / quién obtiene el resultado. Más lecturas para más tarde aquí .
Pregunta introspección para aprender bien: 1 min
Ajustemos un poco la pregunta:
Porque el aprendizaje
Taskcubre automáticamente los otros dos (y responde a su pregunta)Pasar rápidamente la sintaxis de azúcar: 5 minutos
Antes de la conversión (método original)
internal static int Method(int arg0, int arg1) { int result = arg0 + arg1; IO(); // Do some long running IO. return result; }un método de tarea para llamar al método anterior
internal static Task<int> MethodTask(int arg0, int arg1) { Task<int> task = new Task<int>(() => Method(arg0, arg1)); task.Start(); // Hot task (started task) should always be returned. return task; }¿Mencionamos esperar o asíncrono? No. Llame al método anterior y obtendrá una tarea que puede monitorear. Ya sabes lo que devuelve la tarea ... un número entero.
Llamar a una tarea es un poco complicado y es cuando las palabras clave comienzan a aparecer. Llamemos MethodTask ()
internal static async Task<int> MethodAsync(int arg0, int arg1) { int result = await HelperMethods.MethodTask(arg0, arg1); return result; }Mismo código de arriba agregado como imagen de abajo:
awaitasync(sintaxis obligatoria)Asynccomo prefijo (estándar de codificación)awaites fácil de entender pero los dos restantes (async,Async) pueden no ser :). Así, se debe hacer mucho más sentido para el compilador lee though.Further para más adelante aquíComparta la confusión de un desarrollador: 5 minutos
Un desarrollador ha cometido un error al no implementar, ¡
Taskpero aún funciona! Intente comprender la pregunta y solo la respuesta aceptada que se proporciona aquí . Espero que hayas leído y entendido completamente. El resumen es que es posible que no veamos / implementemos 'Tarea' pero se implementa en algún lugar de una clase principal. Del mismo modo, en nuestro ejemplo, llamar a un ya construidoMethodAsync()es mucho más fácil que implementar ese método con unTask(MethodTask()) nosotros mismos. A la mayoría de los desarrolladores les resulta difícil entenderTaskscómo convertir un código a uno asíncrono.Consejo: intente encontrar una implementación Async existente (como
MethodAsyncoToListAsync) para externalizar la dificultad. Por lo tanto, solo tenemos que lidiar con Async y esperar (que es fácil y bastante similar al código normal)Problema: cambie rápidamente una implementación del mundo real de código normal a operación asíncrona: 2 minutos
La línea de código que se muestra a continuación en la Capa de datos comenzó a romperse (en muchos lugares). Porque actualizamos parte de nuestro código de .Net framework 4.2. * A .Net core. ¡Tuvimos que arreglar esto en 1 hora en toda la aplicación!
¡pan comido!
Asyncyawaitde código.la línea del código de llamada se cambió así
La firma del método cambió de
Contract GetContract(int contractnumber)a
async Task<Contract> GetContractAsync(int contractnumber)el método de llamada también se vio afectado:
GetContractAsync(123456);fue llamado comoGetContractAsync(123456).Result;¡Lo cambiamos por todas partes en 30 minutos!
¡Pero el arquitecto nos dijo que no usáramos la biblioteca EntityFramework solo para esto! ¡Uy! ¡drama! Luego hicimos una implementación de Tarea personalizada (yuk). Que ya sabes cómo. Sigue siendo fácil! .. todavía yuk ..
¿A dónde seguir? Hay un maravilloso video rápido que podríamos ver sobre la conversión de llamadas síncronas a asíncronas en ASP.Net Core , quizás esa sea la dirección que tomaría después de leer esto.
fuente
Todas las respuestas aquí usan
Task.Delay()o alguna otraasyncfunción incorporada. Pero aquí está mi ejemplo que no usa ninguna de esasasyncfunciones:fuente
task.Wait();y cómo se puede utilizar para evitar asíncrono / demonios esperan: PEsta respuesta tiene como objetivo proporcionar información específica de ASP.NET.
Al utilizar async / await en el controlador MVC, es posible aumentar la utilización del grupo de subprocesos y lograr un rendimiento mucho mejor, como se explica en el siguiente artículo,
http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4
fuente
Asíncrono y espera explicación simple
Analogia simple
Una persona puede esperar su tren matutino. Esto es todo lo que están haciendo, ya que esta es su tarea principal que están realizando actualmente. (programación síncrona (¡lo que normalmente haces!))
Otra persona puede esperar su tren matutino mientras fuma un cigarrillo y luego toma su café. (Programación asincrónica)
¿Qué es la programación asincrónica?
La programación asincrónica es donde un programador elegirá ejecutar parte de su código en un hilo separado del hilo principal de ejecución y luego notificará al hilo principal cuando se complete.
¿Qué hace realmente la palabra clave asíncrona?
Prefijar la palabra clave asíncrona a un nombre de método como
permite al programador usar la palabra clave wait al llamar a tareas asincrónicas. Eso es todo lo que hace.
¿Porque es esto importante?
En muchos sistemas de software, el hilo principal está reservado para operaciones específicamente relacionadas con la interfaz de usuario. Si estoy ejecutando un algoritmo recursivo muy complejo que tarda 5 segundos en completarse en mi computadora, pero lo estoy ejecutando en el subproceso principal (subproceso de interfaz de usuario) Cuando el usuario intenta hacer clic en cualquier cosa de mi aplicación, parecerá congelado ya que mi hilo principal se ha puesto en cola y actualmente está procesando demasiadas operaciones. Como resultado, el hilo principal no puede procesar el clic del mouse para ejecutar el método desde el clic del botón.
¿Cuándo usas Async y Await?
Utilice las palabras clave asincrónicas idealmente cuando esté haciendo algo que no implique la interfaz de usuario.
Digamos que está escribiendo un programa que permite al usuario dibujar en su teléfono móvil, pero cada 5 segundos verificará el clima en Internet.
Deberíamos estar esperando la llamada que la encuesta llama cada 5 segundos a la red para conocer el clima, ya que el usuario de la aplicación necesita seguir interactuando con la pantalla táctil del móvil para dibujar imágenes bonitas.
¿Cómo se usa Async y Await?
Siguiendo con el ejemplo anterior, aquí hay un pseudocódigo de cómo escribirlo:
Notas adicionales - Actualización
Olvidé mencionar en mis notas originales que en C # solo puede esperar los métodos que están envueltos en Tareas. por ejemplo, puede esperar este método:
No puede esperar métodos que no sean tareas como esta:
No dude en revisar el código fuente de la clase Task aquí .
fuente
Asíncrono / Aguardar
En realidad, Async / Await son un par de palabras clave que son simplemente azúcar sintáctica para crear una devolución de llamada de una tarea asincrónica.
Tomemos como ejemplo esta operación:
El código anterior tiene varias desventajas. Los errores no se transmiten y es difícil de leer. Pero Async y Await vienen a ayudarnos:
Las llamadas en espera deben estar en métodos asíncronos. Esto tiene algunas ventajas:
NOTA : Async y Await se usan con llamadas asincrónicas para no realizarlas. Tienes que usar Task Libary para esto, como Task.Run ().
Aquí hay una comparación entre soluciones de espera y ninguna de espera
Esta es la solución no asíncrona:
Este es el método asíncrono:
En realidad, puede llamar a un método asíncrono sin la palabra clave wait pero esto significa que cualquier Excepción aquí se traga en el modo de liberación:
Async y Await no son para computación paralela. Se utilizan para no bloquear su hilo principal. Cuando se trata de asp.net o aplicaciones de Windows, bloquear su hilo principal debido a una llamada de red es algo malo. Si haces esto, tu aplicación no responderá o incluso se bloqueará.
Echa un vistazo a ms docs para más ejemplos.
fuente
Para ser honesto, sigo pensando que la mejor explicación es la del futuro y las promesas en Wikipedia: http://en.wikipedia.org/wiki/Futures_and_promises
La idea básica es que tiene un grupo separado de subprocesos que ejecutan tareas de forma asincrónica. Al usarlo. Sin embargo, el objeto promete que ejecutará la operación en algún momento y le dará el resultado cuando lo solicite. Esto significa que se bloqueará cuando solicite el resultado y no haya terminado, pero de lo contrario se ejecutará en el grupo de subprocesos.
A partir de ahí, puede optimizar las cosas: algunas operaciones se pueden implementar de forma asíncrona y puede optimizar cosas como la E / S de archivos y la comunicación de red agrupando las solicitudes posteriores y / o reordenándolas. No estoy seguro de si esto ya está en el marco de tareas de Microsoft, pero si no lo fuera, sería una de las primeras cosas que agregaría.
En realidad, puede implementar el tipo de patrón futuro con rendimientos en C # 4.0. Si desea saber exactamente cómo funciona, puedo recomendar este enlace que hace un trabajo decente: http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/ . Sin embargo, si comienza a jugar con usted mismo, notará que realmente necesita soporte de idiomas si desea hacer todas las cosas interesantes, que es exactamente lo que hizo Microsoft.
fuente
Vea este violín https://dotnetfiddle.net/VhZdLU (y mejórelo si es posible) para ejecutar una aplicación de consola simple que muestra los usos de Task, Task.WaitAll (), asíncrono y espera operadores en el mismo programa.
Este violín debería borrar el concepto del ciclo de ejecución.
Aquí está el código de ejemplo
Seguimiento procedente de la ventana de salida:
fuente
fuente
En un nivel superior:
1) La palabra clave asíncrona permite esperar y eso es todo lo que hace. La palabra clave asincrónica no ejecuta el método en un hilo separado. El método f async de inicio se ejecuta sincrónicamente hasta que llegue a esperar en una tarea que requiere mucho tiempo.
2) Puede esperar un método que devuelva Tarea o Tarea de tipo T. No puede esperar un método vacío asíncrono.
3) En el momento en que el hilo principal se encuentra en espera de una tarea que requiere mucho tiempo o cuando se inicia el trabajo real, el hilo principal vuelve al llamador del método actual.
4) Si el hilo principal ve aguardar en una tarea que aún se está ejecutando, no la espera y vuelve al llamador del método actual. De esta manera, la aplicación sigue siendo receptiva.
5) Aguardar en la tarea de procesamiento, ahora se ejecutará en un hilo separado del grupo de hilos.
6) Cuando se completa esta tarea de espera, todo el código a continuación será ejecutado por el hilo separado
A continuación se muestra el código de muestra. Ejecútelo y verifique la identificación del hilo
fuente
La manera en que yo entiendo que es también, debe haber un tercer mandato añadido a la mezcla:
Task.Asynces solo un calificador que pones en tu método para decir que es un método asincrónico.TaskEs el retorno de laasyncfunción. Se ejecuta de forma asincrónica.Eres
awaituna tarea. Cuando la ejecución del código llega a esta línea, el control salta de nuevo a la persona que llama de su función original circundante.Si por el contrario, se asigna el retorno de una
asyncfunción (por ejemploTask) a una variable, cuando la ejecución de código llega a esta línea, simplemente continúa más allá de esa línea en la función que rodea , mientras que lasTaskejecuta de forma asíncrona.fuente
Este artículo MDSN: Programación asincrónica con asíncrono y espera (C #) lo explica explícitamente:
fuente
En el siguiente código, el método HttpClient GetByteArrayAsync devuelve una tarea, getContentsTask. La tarea es una promesa de producir la matriz de bytes real cuando se completa la tarea. El operador de espera se aplica a getContentsTask para suspender la ejecución en SumPageSizesAsync hasta que se complete getContentsTask. Mientras tanto, el control se devuelve a la persona que llama de SumPageSizesAsync. Cuando getContentsTask finaliza, la expresión de espera se evalúa como una matriz de bytes.
fuente
A continuación se muestra el código que lee el archivo de Excel abriendo el cuadro de diálogo y luego usa asíncrono y espera para ejecutar de forma asíncrona el código que lee una a una línea de Excel y se une a la cuadrícula
fuente
Las respuestas aquí son útiles como una guía general sobre wait / async. También contienen algunos detalles acerca de cómo se espera / async está conectado. Me gustaría compartir con ustedes alguna experiencia práctica que deben saber antes de usar este patrón de diseño.
El término "esperar" es literal, por lo que cualquier subproceso en el que lo llame esperará el resultado del método antes de continuar. En primer plano , esto es un desastre . El hilo de primer plano conlleva la carga de construir su aplicación, incluidas las vistas, los modelos de vista, las animaciones iniciales y cualquier otra cosa que haya bloqueado con esos elementos. Entonces, cuando espera el hilo de primer plano, detiene la aplicación. El usuario espera y espera cuando nada parece suceder. Esto proporciona una experiencia de usuario negativa.
Ciertamente puede esperar un hilo de fondo usando una variedad de medios:
El código completo para estos comentarios está en https://github.com/marcusts/xamarin-forms-annoyances . Vea la solución llamada AwaitAsyncAntipattern.sln.
El sitio de GitHub también proporciona enlaces a una discusión más detallada sobre este tema.
fuente
async / awaites el azúcar sintáctico para devoluciones de llamada, no tiene nada que ver con el enhebrado. msdn.microsoft.com/en-us/magazine/hh456401.aspx Es para el código no vinculado a la CPU, por ejemplo, esperando la entrada o un retraso.Task.Runsolo debe usarse para código enlazado a la CPU blog.stephencleary.com/2013/10/…The term "await" is literal, so whatever thread you call it on will wait for the result of the method before continuing.Esto no es cierto, tal vez te refieres a Task.Wait ()? Cuando lo usaawait, establece el resto del método como una continuación que se ejecutará cuando se complete lo que esperaba. Sale del método en el que lo usó, por lo que la persona que llama puede continuar. Luego, cuando la línea esperada está realmente completa, finaliza el resto de ese método en algún subproceso (generalmente un subproceso de trabajo).async/awaitse trata de liberar .NET Threads. Cuando realizaawaituna operación verdaderamente asíncrona (como File.WriteAsync de .NET), suspende el resto del método que utilizóawait, para que la persona que llama pueda continuar y potencialmente terminar su propósito. No hay bloqueo de subprocesos o espera de laawaitoperación -ed Cuandoawaitse completa la operación que editó, el resto delasync/awaitmétodo se coloca en un hilo y se ejecuta (similar a una idea de devolución de llamada).