tpl sincrónico sincronicas sincronica sincrona significado run que parallel new multi library how example entre ejemplos diferencias create conexion comunicacion caracteristicas asincronica asincrona asynchronous task-parallel-library

asynchronous - sincronicas - TaskCompletionSource-Intentando entender el trabajo asincrónico sin hilos



significado de sincronica (2)

Estoy tratando de comprender el propósito de TaskCompletionSource y su relación con el trabajo asincrónico / sin hilos. Creo que tengo una idea general, pero quiero asegurarme de que mi comprensión sea correcta.

Primero comencé a buscar en la Biblioteca de tareas paralelas (TPL) para descubrir si había una buena manera de crear su propio trabajo sin hilo / asincrónico (digamos que está tratando de mejorar la escalabilidad de su sitio ASP.NET) más la comprensión del TPL parece que será muy importante en el futuro ( async / await ). Lo que me llevó a TaskCompletionSource .

Desde mi punto de vista, parece que agregar TaskCompletionSource a una de tus clases no hace mucho para que la codificación sea asincrónica; si todavía está ejecutando el código de sincronización, la llamada a su código se bloqueará. Creo que esto es cierto incluso para las API de Microsoft. Por ejemplo, digamos en DownloadStringTaskAsync fuera de la clase WebClient , cualquier código de configuración / sincronización que estén haciendo inicialmente se bloqueará. El código que está ejecutando debe ejecutarse en algún subproceso, ya sea el actual o tendrá que derivar uno nuevo.

Por lo tanto, usa TaskCompletionSource en su propio código cuando llama a otras llamadas async de Microsoft para que el cliente de sus clases no tenga que crear un nuevo hilo para que su clase no se bloquee.

No estoy seguro de cómo Microsoft hace sus API asincrónicas internamente. Por ejemplo, hay un nuevo método async fuera del SqlDataReader para .Net 4.5. Sé que hay puertos de terminación IO. Creo que es una abstracción de nivel inferior (C ++?) Que probablemente la mayoría de los desarrolladores de C # no usarán. No estoy seguro de si los puertos de terminación IO funcionarán para las llamadas de red o de base de datos (HTTP) o si solo se utilizan para el archivo IO.

Entonces la pregunta es, ¿estoy en lo correcto en mi entendimiento correcto? ¿Hay ciertas cosas que he representado incorrectamente?


Me gusta la explicación que se proporcionó en http://tutorials.csharp-online.net/TaskCompletionSource

(Lo siento, el enlace puede estar muerto en este momento)

Los primeros dos párrafos están debajo

Hemos visto cómo Task.Run crea una tarea que ejecuta un delegado en un subproceso agrupado (o no agrupado). Otra forma de crear una tarea es con TaskCompletionSource.

TaskCompletionSource le permite crear una tarea de cualquier operación que se inicie y termine un tiempo después. Funciona proporcionándole una tarea "esclava" que maneja manualmente, indicando cuándo finaliza o falla la operación. Esto es ideal para el trabajo vinculado a E / S: obtiene todos los beneficios de las tareas (con su capacidad para propagar valores de retorno, excepciones y continuas) sin bloquear un hilo durante la operación.

Para usar TaskCompletionSource, simplemente crea una instancia de la clase. Expone una propiedad Tarea que devuelve una tarea en la que puede esperar y adjuntar continuaciones, al igual que con cualquier otra tarea. La tarea, sin embargo, está controlada completamente por el objeto TaskCompletionSource a través de los siguientes métodos:

public class TaskCompletionSource<TResult> { public void SetResult(TResult result); public void SetException (Exception exception); public void SetCanceled(); public bool TrySetResult (TResult result); public bool TrySetException (Exception exception); public bool TrySetCanceled(); ... }

Llamar a cualquiera de estos métodos señala la tarea, colocándola en un estado completado, fallado o cancelado (cubriremos este último en la sección "Cancelación"). Se supone que debes llamar a uno de estos métodos exactamente una vez: si se vuelve a llamar, SetResult, SetException o SetCanceled generarán una excepción, mientras que los métodos Try * devolverán false.

El siguiente ejemplo imprime 42 después de esperar cinco segundos:

var tcs = new TaskCompletionSource<int>(); new Thread (() => { Thread.Sleep (5000); tcs.SetResult (42); }) .Start(); Task<int> task = tcs.Task; // Our "slave" task. Console.WriteLine(task.Result); // 42

Otras citas interesantes

El poder real de TaskCompletionSource es crear tareas que no atan hilos.

.. y luego

Nuestro uso de TaskCompletionSource sin un hilo significa que un hilo se activa solo cuando se inicia la continuación, cinco segundos después. Podemos demostrar esto iniciando 10,000 de estas operaciones a la vez sin error o consumo excesivo de recursos:


TaskCompletionSource se usa para crear objetos Task que no ejecutan código.

Son utilizados bastante por las nuevas API asincrónicas de Microsoft, cada vez que hay operaciones asíncronas basadas en E / S (u otras operaciones asincrónicas no basadas en CPU, como un tiempo de espera). Además, cualquier método de async Task que escriba usará TCS para completar su Task devuelta.

Tengo una publicación de blog Creando tareas que analiza diferentes formas de crear instancias de Task . Está escrito desde una perspectiva async / await (no es una perspectiva de TPL), pero aún se aplica aquí.

También vea las excelentes publicaciones de Stephen Toub: