run method example ejemplo create convert await async multithreading task-parallel-library async-await c#-5.0

multithreading - method - Diferencia entre TPL y async/await(manejo de hilos)



threadpool c# ejemplo (2)

Creo que el TPL (TaskFactory.Startnew) funciona de manera similar a ThreadPool.QueueUserWorkItem, ya que pone en cola el trabajo en un subproceso en el grupo de subprocesos.

Bastante mucho

Por lo que he estado leyendo, parece que async / await solo "a veces" crea un nuevo hilo.

En realidad, nunca lo hace. Si quieres multihilo, debes implementarlo tú mismo. Hay un nuevo método Task.Run que es solo una forma abreviada de Task.Factory.StartNew , y es probablemente la forma más común de iniciar una tarea en el grupo de subprocesos.

Si estuviera trabajando con puertos de finalización de E / S, puedo ver que no tiene que crear un nuevo subproceso, pero de lo contrario pensaría que tendría que hacerlo.

Bingo. Así que los métodos como Stream.ReadAsync realidad crearán un contenedor de Task alrededor de un IOCP (si el Stream tiene un IOCP).

También puede crear algunas "tareas" que no sean de E / S ni CPU. Un ejemplo simple es Task.Delay , que devuelve una tarea que se completa después de algún período de tiempo.

Lo bueno de async / await es que puede poner en cola algunos trabajos en el grupo de subprocesos (por ejemplo, Task.Run ), realizar alguna operación vinculada a E / S (por ejemplo, Stream.ReadAsync ) y realizar otra operación (por ejemplo, Task.Delay ) ... y son todas tareas! Pueden Task.WhenAll o usarse en combinaciones como Task.WhenAll .

Se puede await cualquier método que devuelva Task , no tiene que ser un método async . Por Task.Delay tanto, las Task.Delay y I / O-bound solo usan TaskCompletionSource para crear y completar una tarea; lo único que se hace en el grupo de subprocesos es la finalización real de la tarea cuando ocurre el evento (tiempo de espera, finalización de E / S, etc.).

Supongo que mi comprensión de FromCurrentSynchronizationContext siempre fue un poco borrosa también. Siempre a través de él fue, en esencia, el hilo de la interfaz de usuario.

Escribí un artículo en SynchronizationContext . La mayoría de las veces, SynchronizationContext.Current :

  • es un contexto de interfaz de usuario si el subproceso actual es un subproceso de interfaz de usuario.
  • es un contexto de solicitud ASP.NET si el subproceso actual está atendiendo una solicitud ASP.NET.
  • es un contexto de agrupación de hilos de lo contrario.

Cualquier hilo puede establecer su propio SynchronizationContext , por lo que hay excepciones a las reglas anteriores.

Tenga en cuenta que el operador de Task predeterminado programará el resto del método async en el SynchronizationContext actual si no es nulo ; De lo contrario, va en el TaskScheduler actual. Esto no es tan importante hoy, pero en el futuro será una distinción importante.

Escribí mi propia introducción de async / await en mi blog, y Stephen Toub recientemente publicó una excelente FAQ de async / await .

Con respecto a "concurrencia" frente a "multihilo", consulte esta pregunta SO relacionada . Yo diría que async permite la concurrencia, que puede o no ser multiproceso. Es fácil de usar await Task.WhenAll o await Task.WhenAny para hacer un procesamiento concurrente, y a menos que uses explícitamente el grupo de hilos (ej., Task.Run o ConfigureAwait(false) ), entonces puedes tener múltiples operaciones concurrentes en progreso al mismo tiempo (p. ej., varias E / S u otros tipos como Delay ), y no hay un hilo necesario para ellos. Utilizo el término "concurrencia de un solo hilo" para este tipo de escenario, aunque en un host ASP.NET, realmente puede terminar con "concurrencia de cero hilos". Que es muy dulce.

Tratando de entender la diferencia entre TPL y async / await cuando se trata de la creación de hilos.

Creo que el TPL ( TaskFactory.StartNew ) funciona de manera similar a ThreadPool.QueueUserWorkItem que ThreadPool.QueueUserWorkItem en cola el trabajo en un subproceso en el grupo de subprocesos. Eso es, por supuesto, a menos que use TaskCreationOptions.LongRunning que crea un nuevo hilo.

Pensé que async / await funcionaría de manera similar:

TPL:

Factory.StartNew( () => DoSomeAsyncWork() ) .ContinueWith( (antecedent) => { DoSomeWorkAfter(); },TaskScheduler.FromCurrentSynchronizationContext());

Async / Await :

await DoSomeAsyncWork(); DoSomeWorkAfter();

sería idéntico. Por lo que he estado leyendo, parece que async / await solo "a veces" crea un nuevo hilo. Entonces, ¿cuándo crea un nuevo hilo y cuándo no crea un nuevo hilo? Si estuviera trabajando con puertos de finalización de E / S, puedo ver que no tiene que crear un nuevo subproceso, pero de lo contrario creo que tendría que hacerlo. Supongo que mi comprensión de FromCurrentSynchronizationContext siempre fue un poco borrosa también. Siempre a través de él fue, en esencia, el hilo de la interfaz de usuario.


async / await básicamente simplifica los métodos ContinueWith (Continuaciones en estilo de paso de continuación )

No introduce la concurrencia: todavía tiene que hacerlo usted mismo (o use la versión Async de un método de marco).

Entonces, la versión C # 5 sería:

await Task.Run( () => DoSomeAsyncWork() ); DoSomeWorkAfter();