Mostrando entradas con la etiqueta Multithreading. Mostrar todas las entradas
Mostrando entradas con la etiqueta Multithreading. Mostrar todas las entradas

jueves, 1 de marzo de 2018

Receta Multithreading en C# No. 6-1: Usar la Estructura de Datos Concurrente ConcurrentDictionary

1. Problema

Usar la estructura de datos basada en clave/valor ConcurrentDictionary.

2. Solución

ConcurrentDictionary es una estructura de datos -tipo diccionario- con capacidad de control de acceso -thread-safe-. Para las operaciones de lectura no es necesario bloquear la estructura, sin embargo para escribir nuevos elementos sí (Agafonov, 2013).


Vale agregar que las operaciones Count, IsEmpty, Keys, Values, CopyTo y ToArray requieren bloquear el acceso total a la estructura para poder ser efectuadas. De aquí se recomienda no ser usadas frecuentamente, pues el desempeño se verá significativamente afectado (Aganofov).

3. Código C#



Prueba de ejecución:
Tiempo ejecución lectura y escritura de Dictionary y ConcurrentDictionary
Figura 1. Tiempo ejecución lectura y escritura de Dictionary y ConcurrentDictionary.

En la Figura 1 se muestra que el desempeño de escritura de un objeto Dictionary es mucho mejor que un objeto ConcurrentDictionary. Los resultados son mejor en lectura por parte del ConcurrentDictionary, pero no llega a estar muy por encima de Dictionary.


Aunque la prueba anterior no es definitiva respecto al desempeño, sí que nos puede dar una perspectiva esencial para determinar cuál estructura de datos escoger para el tipo de problema que estamos resolviendo.

4. Literatura & Enlaces

Agafonov, E. Multithreading in C# 5.0 Cookbook. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.

O

sábado, 24 de febrero de 2018

Receta Multithreading en C# No. 5-9: Usar Tipos Dinámicos con el Operador await

1. Problema

Usar el operadir await con un tipo dinámico de C#.

2. Solución

Para esta receta se usa el paquete ImpromptuInterface: manejo de tipos dinámicos para la versión 4.0 o superiores de C#. Este paquete se agrega desde el administrador de paquetes NuGet (Agafonov, 2013).

3. Código C#

Archivo C# Programa.cs [enlace alternativo]:


Prueba de ejecución:

La tarea se está ejecutando en el thread con ID: 1. ¿Thread en el pool de threads?: true 
La tarea se está ejecutando en el thread con ID: 2. ¿Thread en el pool de threads?: true 

Repositorio: https://github.com/Fhernd/Recetas.Multithreading.CSharp

4. Literatura & Enlaces

Agafonov, E. Multithreading in C# 5.0 Cookbook. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.
NuGet Gallery | ImpromptuInterface 6.2.2 (2018). Recuperado desde: https://www.nuget.org/packages/ImpromptuInterface/
O

miércoles, 13 de julio de 2016

Receta Multithreading en C# No. 5-8: Diseño Tipo Awaitable Personalizado

Índice

1. Introducción
2. Palabras Clave
3. Problema
4. Solución
5. Discusión de la Solución
5.1 Especificación de C# 5.0 para tipos awaitable personalizados
5.2 Interfaz InotifyCompletion
Conclusiones
Literatura & Enlaces

1. Introducción

Con esta receta C# se desea ilustrar cómo crear un tipo awaitable personalizado compatible con el operador asincrónico await. Más que de una aplicación concreta, el propósito es ilustrar en sentido académico cómo el programador puede crear una implementación personalizada de un tipo awaitable. Se describen los requerimientos para la definición de un tipo awaitable personalizado siguiendo la especificación del parágrafo 7.7.7.1 de la versión de C# 5.0. La sección práctica recurre al uso de la interfaz INotifyCompletion para la calendarización de continuaciones cuando el tipo await personalizado haya finalizado.

2. Palabras Clave

  • Await
  • Continuación
  • Interfaz
  • INotifyCompletion

3. Problema

Crear una implementación personalizada de un awaitable compatible con la función asincrónica await.

4. Solución

En .NET Framework se cuenta con la interfaz INotifyCompletion para el diseño de un tipo awaitable personalizado.

5. Discusión de la Solución

5.1 Especificación de C# 5.0 para tipos awaitable personalizados

En el parágrafo 7.7.7.1 (Agafonov, 2013) se definen los requerimientos para la definición de expresiones awaitable

Una expresión t es awaitable si se respeta cualquiera de estas reglas: 
  • La expresión t es un tipo de dato dynamic en tiempo de compilación. 
  • La expresión t tiene un método de instancia o método de extensión llamado GetAwaiter() sin parámetros regulares o tipos paramétricos y un tipo de retorno X que debe cumplir estas especificaciones: 
    • X debe implementar la interfaz System.Runtime.CompilerServices.INotifyCompletion (INotifyCompletion Interface", 2016).
    • X cuenta con una propiedad de sólo lectura pública de tipo bool llamada IsCompleted.
    • X cuenta un método de instancia público sin parámetros regulares ni paramétricos llamado GetResult().
Esta descripción está basada en la lectura del documento de especificación del lenguaje de programación C# que el lector puede encontrar en este enlace: CSharp 5.0 Language Specification.pdf.

Esta especificación se sigue en la sección práctica de esta receta para el diseño de un tipo awaitable personalizado.

5.2 Interfaz INotifyCompletion

La interfaz INotifyCompletion (namespace System.Runtime.CompilerServices) representa una operación que programa continuaciones una vez que finaliza su ejecución.

6. Práctica: Diseño de Tipo Awaitable Personalizado

Esta receta sigue el parágrafo 7.7.7.1 de la especificación de C# 5.0.

En primer lugar se implementa el tipo awaitable personalizado: 

La clase AwaitablePersonalizado (líneas 6-31) representa la implementación del tipo awaitable personalizado. De acuerdo a la especificación de C# 5.0, esta clase escribe el método GetAwaiter() (líneas 27-30); además retorna el tipo que implementa la interfaz INotifyCompletion: AwaiterPersonalizado.




Continuando, la clase AwaiterPersonalizado (líneas 11-77) implementa la interfaz INotifyCompletion. Estas son las características de esta clase: 
  • Líneas 25-28: Propiedad pública de sólo lectura IsCompleted para determinar si la ejecución de la operación ha finalizado.
  • Líneas 43-46: Método GetResult() que retorna el resultado de la operación.
Por último con la clase PersonalizacionAwait prueba el tipo awaitable personalizado: 

Archivo C# PersonalizacionAwait.cs [Enlace alternativo][Enlace alternativo]: 

En las líneas 24-33 se llevan a cabo estas operaciones: 
  • Línea 26: Se crea un objeto del tipo awaitable personalizado para ejecución sincrónica.
  • Línea 27: Se usa el operador await sobre el tipo awaitable personalizado.
  • Línea 28: Se muestra en la salida estándar el resultado de la ejecución sincrónica.
  • Línea 30: Creación de objeto de tipo AwaitablePersonalizado para ejecución asincrónica.
  • Línea 31: Uso operación asincrónica await para invocación asincrónica.
  • Línea 32: Muestra en la salida estándar el resultado de la operación asincrónica.
Prueba de ejecución: 

7. Conclusiones

Se ha demostrado como en C# es posible crear un tipo awaitable personalizado para operar con la función asincrónica await. Este conocimiento debe alentar al programador a incursionar o sentir curiosidad por temas avanzados que pueden tratarse con C#.


La última receta multithreading de esta serie Usando C# 5.0 enseña al programador a usar el operador asincrónico await con el tipo dynamic.

8. Literatura & Enlaces

Agafonov, E. (2013). Multithreading in C# 5.0 Cookbook. United States: Packt Publishing.
INotifyCompletion Interface (System.Runtime.CompilerServices) (2016, julio 13). Recuperado desde https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.inotifycompletion(v=vs.110).aspx


O

martes, 12 de julio de 2016

Receta Multithreading en C# No. 5-7: Gestión Irregularidades de Tipo de Retorno void en Métodos Asincrónicos

Índice

1. Introducción
2. Palabras Clave
3. Problema
4. Solución
5. Discusión de la Solución
5.1 Tipo de retorno void
6. Práctica: Gestión de Tipo de Retorno void en Métodos Asincrónicas
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

Llega la oportunidad de explorar cómo en un método asincrónico con tipo de retorno void se comporta el flujo de ejecución de una aplicación con múltiples tareas en ejecución. El propósito principal es conocer los problemas que compromete usar este tipo de retorno en la gestión de excepciones por parte del programador. En la sección práctica se demuestra los casos irregulares en la generación de excepciones en dos situaciones: bloque try-catch y una expresión lambda.

2. Palabras Clave

  • Asincronismo
  • Excepción
  • Expresión lambda
  • Operación asincrónica
  • Pool de threads
  • Thread
  • try-catch

3. Problema

Gestionar el tipo de retorno void en operaciones asincrónicas.

4. Solución

Aunque existen soluciones para gestionar el tipo de retorno void, en esta receta se describe cuáles son los problemas que generar este tipo de retorno en operaciones asincrónicas.

5. Discusión de la Solución

5.1 Tipo de retorno void

El tipo de retorno void especifica que un método no retorna ningún valor una vez ejecutada las operaciones de su implementación. Esto no tiene ningún problema en métodos sincrónicos. Sin embargo, en operaciones asincrónicas y más en particular en métodos que pueden generar excepciones sí que pueden producirse comportamientos anómalos e irregulares.

Continuando, esto es así porque en el contexto de sincronización la gestión de excepciones se lleva a cabo en el pool de threads; entonces, si una excepción no es gestionada, el proceso general terminará de forma abrupta (Agafonov, 2016).

Aún así, existen mecanismos para gestionar las excepciones como el evento AppDomain.UnhandledException. Este evento ocurre cuando una excepción no es capturada/gestionada ("AppDomain.UnhandledException Event", 2016).

Este es un ejemplo de uso de este evento: 

Archivo C# UsoUnhandledException.cs [Enlace alternativo][Enlace alternativo]: 

6. Práctica: Gestión de Tipo de Retorno void en Métodos Asincrónicos

El siguiente ejemplo adaptado de Agafonov (2013) demuestra cuáles son los problemas que pueden emerger en el uso del tipo de retorno void en una operación asincrónica.

La primera parte empieza con la descripción del método AsyncRetornoTaskConErrores() (líneas 64-69): este método retorna un objeto Task y genera una excepción simulada por medio de una cadena de texto.


Por otra parte, con AsyncRetornoVoidConErrores() (líneas 75-80) se simula también una excepción con una cadena de texto que incluye la palabra Exception.


El propósito con estos dos métodos es demostrar lo que ocurre al invocar una operación asincrónica que produce una excepción.


Como contraste, los métodos AsyncRetornoTask() (líneas 86-91) y AsyncRetornoVoid() (líneas 97-102) no generan ninguna excepción; sin embargo, en el caso de AsyncRetornoVoid() permite hacer la demostración de lo que ocurre con el tipo de retorno void. Mientras que AsyncRetornoTask() facilita la monitorización del estado de ejecución de la tarea asincrónica, gracias al tipo de retorno, por su parte AsyncRetornoVoid() no; para lograrlo se debe esperar un tiempo debido a que no cuenta con mecanismo de monitoreo de la operación asincrónica.


En cuanto al método Ejecutar() (líneas 15-58), estas son las operaciones que se ejecutan: 
  • Líneas 17-18: Definición de un objeto Task que recibe como retorno el objeto Task de AsyncRetornoTask(). Con t.Wait() se espera unos instantes mientras que la tarea asincrónica se completa.
  • Líneas 20-21: Invocación de AsyncRetornoVoid(). El monitoreo del estado de la operación asincrónica sólo se logra con un tiempo de espera. Este tiempo de espera es superior al tiempo ejecución simulado por el método. ¿La razón? El tipo de retorno de la operación asincrónica: void.
  • Líneas 23-29: Invocación de AsyncRetornoTaskConErrores(). El ciclo while comprueba que mientras no se genere ninguna falla se simula un tiempo de espera. Al final, línea 27, se muestra la excepción que se produjo con la invocación de esta método.
  • Líneas 31-55: Sirve al lector como comprobación del comportamiento irregular del manejo de excepciones de operaciones asincrónicas que retornan el tipo void. El lector puede tomar este código y verificar por medios propios lo que ocurre cuando se remueven los comentarios.
Esta es la demostración del código en ejecución: 

7. Conclusiones

Quedó demostrado cómo gestionar el tipo de retorno void de métodos asincrónicos. El no reconocer las problemas en manejo de excepciones en métodos con esta clase de firma puede hacer que un programa genere un comportamiento irregular y afecte la experiencia del usuario.

La próxima receta multithreading explicará cómo diseñar un tipo personalizado de await.

8. Literatura & Enlaces

Agafonov, E. (2013). Multithreading in C# 5.0 Cookbook. United States: Packt Publishing.
AppDomain.UnhandledException Event (System) (2016, julio 12). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception(v=vs.110).aspx


O

lunes, 11 de julio de 2016

Receta Multithreading en C# No. 5-6: Cambiar el Modo de Ejecución Asincrónica

Índice

1. Introducción
2. Palabras Clave
3. Problema
4. Solución
5. Discusión de la Solución
5.1 Método Task.ConfigureAwait()
6. Práctica: Cambio de Ejecución Asincrónico
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

El modo de operación de la invocación de una función asincrónica await puede ser alterado, por ejemplo, en la ejecución de operaciones asincrónicas de una interfaz gráfica de usuario. Esta receta multithreading en C# explica cómo usar el método ConfigureAwait() para configurar la ejecución asincrónica de código que no accede a los componentes de la interfaz gráfica de usuario. La demostración en la sección práctica enseña el uso de este método alternando entre el uso del contexto de sincronización y sin recurrir a él.

2. Palabras Clave

  • Asincronismo
  • Contexto de sincronización
  • Interfaz gráfica de usuario
  • GUI
  • Sincronismo

3. Problema

Configurar el modo de ejecución asincrónico de una tarea.

4. Solución

El método ConfigureAwait() permite la configuración del modo de ejecución asincrónico.

5. Discusión de la Solución

5.1 Método Task.ConfigureAwait()

El método ConfigureAwait() configura el modo de ejecución asincrónica de una tarea. Este método recibe como argumento un valor booleano que en caso de ser true, el modo de ejecución asincrónica captura el contexto desde donde es ejecutada la tarea; en caso contrario la tarea se debe ejecutar sin capturar el contexto de sincronización.

Esta es su firma: 

public ConfiguredTaskAwaitable ConfigureAwait(
bool continueOnCapturedContext
)

6. Práctica: Cambio de Ejecución Asincrónica

La siguiente receta C# explica cómo el programador puede cambiar el modo de ejecución asincrónica.

El método que controla el evento Click (líneas 48-69) del botón que activa las operaciones asincrónicas lleva a cabo estas operaciones: 
  • Línea 51: Asigna el texto Calculando... cuando se inicia la ejecución asincrónica de dos tareas que operan en asincronismo con y sin contexto.
  • Línea 54: Inicia la ejecución de una operación con contexto.
  • Línea 55: Inicia la ejecución de una operación sin contexto.
  • Líneas 61-65: Construcción de la cadena de resultados de las dos operaciones asincrónicas anteriores.
  • Línea 68: Asigna el nuevo texto a la etiqueta de la interfaz gráfica de usuario.
Por otra parte, con el método OperacionContexto() (líneas 75-90) realiza estas operaciones: 
  • Línea 77: Especifica el número de iteraciones que ejecuta este método asincrónico.
  • Líneas 78-79: Creación e inicio de cronómetro.
  • Líneas 81-85: Repite la ejecución de una tarea asincrónica simulada. Aquí la tarea se ejecuta capturando implícitamente el contexto de ejecución.
  • Línea 87: Se detiene el cronómetro.
  • Línea 89: Retorna el tiempo que tomó la ejecución.
De manera análoga, el método OperacionSinContexto() (líneas 96-112) ejecuta estas operaciones: 
  • Línea 98: Especifica el número de iteraciones que ejecuta este método asincrónico.
  • Líneas 99-100: Creación e inicio de cronómetro.
  • Líneas 102-107: Repite la ejecución de una tarea asincrónica simulada. A través del método ConfigureAwait() se establece que el método se debe ejecutar sin capturar el contexto de sincronismo.
  • Línea 109Se detiene el cronómetro.
  • Línea 111: Retorna el tiempo que tomó la ejecución.
Finalmente, con el método Ejecutar() (líneas 19-41) se construye la interfaz gráfica de una aplicación Windows Presentation Foundation (WPF).

Prueba de ejecución: 

7. Conclusiones

Se ha demostrado cómo a través del método ConfigureAwait() se puede alterar el modo de ejecución de una operación asincrónica: con y sin captura de contexto de sincronismo. Quedó claro que cuando no se captura el contexto el desempeño general de la aplicación es superior comparado con la captura del contexto.

Hasta ahora se ha estudiado los métodos asincrónicos que retornan un tipo paramétrico para el tipo Task, sin embargo en la siguiente receta multithreading se estudiará cómo trabajar con operaciones asincrónicas que retornan void.

8. Literatura & Enlaces

Agafonov, E. (2013). Multithreading in C# 5.0 Cookbook. United States: Packt Publishing.
Task.ConfigureAwait Method (Boolean) (System.Threading.Tasks) (2016, julio 11). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.configureawait(v=vs.110).aspx


V

domingo, 3 de julio de 2016

Receta Multithreading en C# No. 5-4: Ejecución en Paralelo de Tareas con await

Índice

1. Introducción
2. Palabras Clave
3. Problema
4. Solución
5. Discusión de la Solución
5.1 Combinación de tareas con Task.WhenAll
6. Práctica: Ejecución en Paralelo de Tareas
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

Aquí se explica cómo el programador puede lograr la ejecución en paralelo de múltiples tareas usando la función asincrónica await. El ejemplo de la sección práctica demuestra que esto es posible a través de la ejecución de dos tareas, cada una con 3 y 5 segundos de retrasa. Al final quedará demostrado que el tiempo máximo de espera será 5 segundos.

2. Palabras Clave

  • await
  • Ejecución en paralelo
  • Función asincrónica
  • Tarea

3. Problema

Ejecutar en paralelo dos o más tareas.

4. Solución

A través del operador await el programador puede implementar código de ejecución en paralelo.

5. Discusión de la Solución

5.1 Combinación de tareas con Task.WhenAll

El método static Task.WhenAll() ("Task.WhenAll Method", 2016) crea una tarea compuesta; una vez que el conjunto de tareas integrales finalicen su ejecución, el flujo de control de ejecución pasa a la tarea compuesta y se continua con la lógica de implementación particular a esta tarea.

Este método cuenta hasta con 4 versiones static sobrecargadas; tal y como se muestra en la siguiente figura: 
Versiones sobrecargadas de Task.WhenAll
Figura 1. Versiones sobrecargadas de Task.WhenAll ("Task.WhenAll Method", 2016).

6. Práctica: Ejecución en Paralelo de Tareas

El siguiente ejemplo en C# demuestra la ejecución de dos tareas en paralelo a través del uso de la función asincrónica await.

El método ObtenerInfoAsync(string, int) (líneas 46-54) representa una operación de ejecución asincrónica. Estas son las operaciones que lleva a cabo: 
  • Línea 48: Simula la ejecución extendida.
  • Líneas 50-53: Retorna cadena de caracteres con la información del thread que ejecuta la tarea.
Por otra parte, con el método ProcesamientoAsincronico() (líneas 25-38) se preparan para ejecución dos tareas; cada una con duración de 3 y 5 segundos. Los resultados se almacenarán en el arreglo de objetos string resultados (línea 30). Cuando estas dos tareas hayan finalizado su ejecución, se muestran los resultados de los threads de ejecución en el ciclo foreach de las líneas 34-37.

En esta captura se presenta el flujo de ejecución de esta interesante receta: 
> Prueba de ejecución (online): http://ideone.com/6yNUeO

7. Conclusiones

El operador await permite al programador del lenguaje de programación C# ejecutar en paralelo dos o más tareas. Hasta ahora se ha visto que el modelo TPL resulta más intuitivo y poderoso que los modelos EAP y APM estudiados en series de recetas multithreading anteriores.

La próxima receta multithreading enseña al programador cómo manipular excepciones en operaciones asincrónicas.

8. Literatura & Enlaces

Agafonov, E. (2013). Multithreading in C# 5.0 Cookbook. United States: Packt Publishing.
Task.WhenAll Method (System.Threading.Tasks) (2016, julio 3). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.whenall(v=vs.110).aspx


V

domingo, 26 de junio de 2016

Receta Multithreading en C# No. 5-2: Operador await en una Expresión Lambda

Índice

1. Introducción
2. Palabras Clave
3. Problema
4. Solución
5. Discusión de la solución
5.1 Operador asincrónico await
5.2 Operador asincrónico async
6. Práctica: Expresión Lambda con Operador Asincrónico await
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

El programador C# puede usar el operador asincrónico await en una expresión lambda. Esta receta multithreading explica cómo usar este operador asincrónico en el cuerpo de declaración, junto con el uso de async en listado de parámetros de la expresión lambda. Para llevar a cabo la demostración programática de esta receta se usará el delegado estándar Func<T, TResult>.

2. Palabras Clave

  • Asincronismo
  • Expresión lambda
  • Sincronismo

3. Problema

Definir la implementación de una expresión lambda usando el operador await.

4. Solución

El cuerpo de la implementación de una expresión lambda puede incluir la invocación de operaciones por medio de await; sin embargo para esto es necesario marcar la firma de la expresión con el operador asincrónico asyncEsta expresión lambda quedará declarada sobre un delegado del tipo Func<T, TResult>.

5. Discusión de la Solución

5.1 Operador asincrónico await

(Nota: En la sección 5.1 de Receta Multithreading en C# No. 5-2: Operador await en una Expresión Lambda se detalla el funcionamiento de este operador.)

5.2 Operador asincrónico async

A través del operador asincrónico el programador C# puede marcar un método, expresión lambda o método anónimo como asincrónico ("async (C# Reference)", 2016). Este un ejemplo para marcar un método nombrado: 
public async Task OperacionAsync()
{
// ...
}

Y para el caso de una expresión lambda: 

async param => {
// ...
}

5.3 Delegado Func<T, TResult>

(Nota: En la sección 2.1 de Delegados en C#: Delegados Func y Action de .NET Framework se explica detallamente el funcionamiento de este tipo de delegado.)

6. Práctica: Composición de una Expresión Lambda con el Operador Asincrónico await

La aplicación consola que se ha construido demuestra cómo definir una expresión lambda especificando en su cuerpo de implementación el operador asincrónico await.

El método ProcesamientoAsincronico() (líneas 26-42) se implementa de la siguiente manera: 
  • Líneas 31-39: Declaración de delegado por medio de la firma Func<T> con la siguiente expresión lambda:
    • Línea 29: Especificación el parámetro nombre antecedido por el operador asincrónico async.
    • Línea 31: Invocación asincrónica de tarea que simula ejecución extendida a través del operador await.
    • Línea 32-36: Retorno con la información del thread en ejecución en la operación asincrónica.
  • Línea 39: Invocación de la expresión lambda por medio del operador asincrónico await.
  • Línea 41: Visualización del resultado de la expresión lambda.
Demostración de la ejecución a través de una aplicación basada en consola construida en Visual Studio 2015
> Prueba de ejecución (online): http://ideone.com/Mg0XL1


En este enlace de GitHub puede encontrar la solución de Visual Studio 2015 y los proyectos asociados a esta receta y otras más: https://github.com/Fhernd/RecetasMultithreadingCSharp

7. Conclusiones

Se ha demostrado que dentro del cuerpo de una expresión lambda es posible usar la función asincrónica await para invocar otras operaciones asincrónicas. Lo anterior siempre y cuando el programador especifique la función asincrónica async en la firma de parámetros de la expresión.

La siguiente receta multithreading explica cómo usar el operador asincrónico await para llamadas asincrónicas consecutivas de tareas.

8. Literatura & Enlaces

Agafonov, E. (2013). Multithreading in C# 5.0 Cookbook. United States: Packt Publishing.
Receta Multithreading en C# No. 5-1: Obtención de Resultados de Tareas Asincrónicas con el Operador await (2016, junio 26). Recuperado desde: http://ortizol.blogspot.com/2016/06/receta-multithreading-en-csharp-no-5-1-obtencion-de-resultados-de-tareas-asincronicas-con-el-operador-await.html
async (C# Reference) (2016, junio 26). Recuperado desde: https://msdn.microsoft.com/en-us/library/hh156513.aspx?f=255&MSPPError=-2147217396
Delegados en C#: Delegados Func y Action de .NET Framework (2016, junio 26). Recuperado desde: http://ortizol.blogspot.com.co/2014/05/delegados-en-csharp--parte-5-delegados-func-y-action-de-dotnet-framework.html


V