una que librería eventos evento ejemplos delegate crear biblioteca c# .net async-await .net-4.5

c# - que - ¿Qué diferencia hace? ¿Ejecutar un delegado de acción ''asincrónico'' con un Task.Run(frente a un delegado de acción predeterminado)?



eventos en c# ejemplos (2)

La diferencia es que estás desperdiciando un hilo y su porción de tiempo asignada.

Cuando bloquea un hilo durante 5 segundos, ese hilo no se puede usar en otras partes de su sistema para hacer el trabajo real de la CPU. También crea un cambio de contexto ya que ese hilo no puede hacer otra cosa.

Cuando Task.Delay ese hilo usando Task.Delay lugar de Thread.Sleep el hilo puede volver al ThreadPool , tomar una tarea en espera y ejecutarla.

Sobre todo, cuando liberas tus hilos cuando puedes, haces que tu aplicación sea más escalable y eficiente, ya que necesita menos recursos para hacer el mismo trabajo o la misma cantidad de recursos para hacer más trabajo.

Cuando su operación es realmente asíncrona, no es necesario utilizar Task.Run (a menos que necesite un hilo de fondo). Puede llamar a ese método y esperar la tarea devuelta:

public async Task<bool> RetrySendEmail(MailMessage message) { bool emailSent = false; for (int i = 0; i < 3; i++) { if (emailSent) break; else await Task.Delay(5000); try { Smtphost.Send(message); emailSent = true; break; } catch (Exception e) { emailSent = false; // log; } } return emailSent; }

Estoy tratando de asentir / esperar y pensé que entendía algunas cosas sobre el uso. Pero aún no está del todo claro cuál sería el beneficio real en un escenario como el de abajo.

Mire el uso de Task.Run. El primer método usa un delegado normal y usa Thread.Sleep pero el segundo usa delegado ''async'' y Task.Delay.

Mi pregunta es: ¿cómo hace esto alguna diferencia en este método (o no)?

El método en sí es un método asíncrono. El código está creando un hilo separado (a través de Task.Run) y este hilo no tiene nada más que hacer que ejecutar ese delegado. Por lo tanto, incluso si cede con una espera en Task.Delay, ¿cuál es el uso en este escenario, ya que el hilo es de todos modos un hilo aislado no utilizado para nada más e incluso si solo utiliza Thread.Sleep, el hilo aún contextualizaría cambiar para ceder a otros hilos para el procesador.

// The task thread uses a async delegate public async Task<bool> RetrySendEmail(MailMessage message) { bool emailSent = false; await (Task.Run(***async ()*** => { for (int i = 0; i < 3; i++) { if (emailSent) break; else // Wait for 5 secs before trying again ***await Task.Delay(5000);*** try { Smtphost.Send(message); emailSent = true; break; } catch (Exception e) { emailSent = false; // log; } } return emailSent; })); } // The task thread uses a normal delegate public async Task<bool> RetrySendEmail(MailMessage message) { bool emailSent = false; await (Task.Run(***()*** => { for (int i = 0; i < 3; i++) { if (emailSent) break; else // Wait for 5 secs before trying again ***Thread.Sleep(5000);*** try { Smtphost.Send(message); emailSent = true; break; } catch (Exception e){ emailSent = false; // log; } } return emailSent; })); }


Mi pregunta es: ¿cómo hace esto alguna diferencia en este método (o no)?

Un par de diferencias

  1. Usar un delegado async dentro de Task.Run significa que realmente ejecuta una Task<Task> . Esto está oculto para ti por el hecho de que Task.Run es asíncrono y desenvuelve la tarea interna para ti, algo que Task.Factory.StartNew no hizo
  2. Cuando utilizas un delegado asíncrono con Task.Run , creas un nuevo hilo y luego await Task.Delay control una vez que await Task.Delay . La continuación se ejecutará en un subproceso de grupo de subprocesos arbitrario. Además, el delegado se transforma en una máquina de estados por el compilador.

    Con el delegado normal, creas un hilo, lo bloqueas sincrónicamente durante 5 segundos y luego continúas en el punto donde lo dejaste. Sin máquinas de estado, sin rendimiento.

Por lo tanto, incluso si cede con una espera en Task.Delay, ¿cuál es el uso en este escenario, ya que el hilo es de todos modos un hilo aislado no utilizado para nada más e incluso si solo utiliza Thread.Sleep, el hilo aún contextualizaría cambiar para ceder a otros hilos para el procesador.

El uso de Task.Run con Task.Run puede ser cuando desee realizar trabajos en CPU y IO encuadernados, todo en un hilo dedicado. Tiene razón al pensar que después de que el delegado asíncrono rinda, regresa en un hilo arbitrario. Sin embargo, si no hubiera utilizado Task.Run y el método async ejecutado desde un subproceso que tuviera un contexto de sincronización personalizado adjunto (como WinformsSynchronizationContext), cualquier trabajo posterior al await devolvería al bucle de mensaje de UI, a menos que lo haya utilizado ConfigureAwait(false) .

A decir verdad, no he visto tantos escenarios donde Task.Run y async se usan correctamente. Pero tiene sentido a veces.