InicioArticulos y noticiasBases de datosProgramaciónForosInternetServiciosContratacionEmail
Tutorial C#
Introduccion a C#
Programacion con C#
Fundamentos de C#
Operadores
Instrucciones
Estrcuturas de control.
Definición de clases
Creación de objetos
Herencia y métodos virtuales
Polimorfismo
Ocultación de miembros
Miembros de tipo
Encapsulación
Espacios de nombres
Importación de espacios de nombres
Espacio de nombres distribuidos
Variables y tipos de datos
Tablas unidimensionales
Tablas multidimensionales
La clase System.Array
Cadenas de texto
Constantes
Orden de inicialización de variables
Métodos
Métodos externos
Constructores
Destructores
Propiedades
Indizadores
Redefinición de operadores
Delegados y eventos
La clase MulticastDelegate
Llamadas asíncronas
Implementación interna de los delegados
Eventos
Estructuras
Boxing y unboxing
Constructores de estructuras
Enumeraciones
Interfaces
Excepciones
Otras instrucciones
Atributos
Definición de nuevos atributos
Lectura de atributos en tiempo de ejecución
Atributos de compilación
Pseudoatributos
Código inseguro
Definición de punteros
Manipulación de punteros
Operadores relacionados con código inseguro
Fijación de variables apuntadas
Novedades de C# 2.0
Genéricos
Tipos parciales
Iteradores
Mejoras en la manipulación de delegados
Tipos anulables
Modificadores de visibilidad de bloques get y set
Clases estáticas
Referencias a espacios de nombres
Supresión temporal de avisos
Atributos condicionales
Incrustación de tablas en estructuras
Modificaciones en el compilador
También puedes ver ...
Creando cadenas de conexión ConnectionStrings en .net 3.5 o visual Studio 2008 usando SqlConnectionStringBuilder
Migración de WSE a WCF (Web Services de 2005 a 2008)
Generar archivos PDF con C#
TransactionScope - Simplificando el trabajo con transacciones.
LinQ To SQL - Un ejemplo sencillo
Cómo activar Intelisense (autocompletado) en el Web.config
Leer un campo XML de SQL Server 2005 con C#
TripleDES - Un ejemplo practico en C#
Mostrar un GridView dentro de un DataList
String.Format

Afiliados
La Web del programador
MundoProgramacion


 

Llamadas asíncronas

    La forma de llamar a métodos que hasta ahora se ha explicado realiza la llamada de manera síncrona, lo que significa que la instrucción siguiente a la llamada no se ejecuta hasta que no finalice el método llamado. Sin embargo, a todo método almacenado en un objeto delegado también es posible llamar de manera asíncrona a través de los métodos del mismo, lo que consiste en que no se espera a que acabe de ejecutarse para pasar a la instrucción  siguiente a su llamada  sino que su ejecución se deja en manos de un hilo aparte que se irá ejecutándolo en paralelo con el hilo llamante. 

    Por tanto los delegados proporcionan un cómodo mecanismo para ejecutar cualquier método asíncronamente, pues para ello basta introducirlo en un objeto delegado del tipo apropiado. Sin embargo, este mecanismo de llamada asíncrona tiene una limitación, y es que sólo es válido para objetos delegados que almacenen un único método.

    Para hacer posible la realización de llamadas asíncronas, aparte de los métodos heredados de System.MulticastDelegate todo delegado cuenta con estos otros dos que el compilador define a su medida en la clase en que traduce la definición de su tipo:


 IAsyncResult BeginInvoke(<parámetros>, AsyncCallback cb,  Object o)


 <tipoRetorno> EndInvoke(<parámetrosRefOut>, IASyncResult ar)

    BeginInvoke() crea un hilo que ejecutará los métodos almacenados en el objeto delegado sobre el que se aplica con los parámetros indicados en <parámetros> y devuelve un objeto IAsyncResult que almacenará información relativa a ese hilo (por ejemplo, a través de su propiedad de sólo lectura bool IsComplete puede consultarse si ha terminado su labor) Sólo tiene sentido llamarlo si el objeto delegado sobre el que se aplica almacena un único método, pues si no se lanza una System.ArgumentException.

    El parámetro cb de BeginInvoke() es un objeto de tipo delegado que puede almacenar métodos a ejecutar cuando el hilo antes comentado finalice su trabajo. A estos métodos el CLR les pasará automáticamente como parámetro el IAsyncResult devuelto por BeginInvoke(), estando así definido el delegado destinado a almacenarlos:


public delegate void
ASyncCallback(IASyncResult obj);

    Por su parte, el parámetro o de BeginInvoke puede usarse para almacenar cualquier información adicional que se considere oportuna. Es posible acceder a él a través de la propiedad object AsyncState del objeto IAsyncResult devuelto por BeginInvoke()

    En caso de que no se desee ejecutar ningún código especial al finalizar el hilo de ejecución asíncrona o no desee usar información adicional, puede darse sin ningún tipo de problema el valor null a los últimos parámetros de BeginInvoke() según corresponda.

    Finalmente, EndInvoke() se usa para recoger los resultados de la ejecución asíncrona de los métodos iniciada a través BeginInvoke() Por ello, su valor de retorno es del mismo tipo que los métodos almacenables en el objeto delegado al que pertenece y en <parámetrosRefOut> se indican los parámetros de salida y por referencia de dichos métodos. Su tercer parámetro es el  IAsyncResult devuelto por el BeginInvoke() que creó el hilo cuyos resultados se solicita recoger y se usa precisamente para identificarlo. Si ese hilo no hubiese terminado aún de realizar las llamadas, se esperará a que lo haga.

    Para ilustrar mejor el concepto de llamadas asíncronas, el siguiente ejemplo muestra cómo encapsular en un objeto delegado un método F() para ejecutarlo asíncronamente:



 
D objDelegado =  new  D (F);
 IAsyncResult hilo = objDelegado.BeginInvoke(3,
new AsyncCallback(M),
"prueba");
 // ... Hacer cosas
 objDelegado.EndInvoke(hilo);

    Donde el método M ha sido definido en la misma clase que este código así:


public static void M(IAsyncResult obj)
{
 Console.WriteLine("Llamado a M() con {0}", obj.AsyncState);
}

    Si entre el BeginInvoke() y el EndInvoke() no hubiese habido ninguna escritura en pantalla, la salida del fragmento de código anterior sería:


 Pasado valor 3 a F()
 
 Llamado a M() con prueba

    La llamada a BeginInvoke() lanzará un hilo que ejecutará el método F() almacenado en objDelegado, pero mientras tanto también seguirá ejecutándose el código del hilo desde donde se llamó a BeginInvoke() Sólo tras llamar a EndInvoke() se puede asegurar que se habrá ejecutado el código de F(), pues mientras tanto la evolución de ambos hilos es prácticamente indeterminable ya que depende del cómo actúe el planificador de hilos.

    Aún si el hilo llamador modifica el valor de alguno de los parámetros de salida o por referencia de tipos valor, el valor actualizado de éstos no será visible para el hilo llamante hasta no llamar a EndInvoke() Sin embargo, el valor de los parámetros de tipos referencia sí que podría serlo. Por ejemplo, dado un código como:



 int x=0;
 Persona p = new Persona("Josan", "7361928-E", 22);
 IAsyncResult res  = objetoDelegado.BeginInvoke(ref x, p, null, null);
 // Hacer cosas...
 objetoDelegado.EndInvoke(ref x, res);

    Si en un punto del código comentado con // Hacer cosas..., donde el hilo asíncrono ya hubiese modificado los contenidos de x y p, se intentase leer los valores de estas variables, sólo se leería el valor actualizado de p. El de x no se vería hasta después de la llamada a EndInvoke()

    Por otro lado, hay que señalar que si durante la ejecución asíncrona de un método se produce alguna excepción, ésta no sería notificada pero provocaría que el hilo asíncrono abortase. Si posteriormente se llamase a EndInvoke() con el IAsyncResult asociado a dicho hilo, se relanzaría la excepción que produjo el aborto y entonces podría tratarse.

    Para optimizar las llamadas asíncronas es recomendable marcar con el atributo OneWay definido en System.Runtime.Remoting.Messaging los métodos cuyo valor de retorno y valores de parámetros de salida no nos importen, pues ello indica a la infraestructura encargada de hacer las llamadas asíncronas que no ha de considerar. Por ejemplo:


[OneWay] public void Método()
{}

    Ahora bien, hay que tener en cuenta que hacer esto implica perder toda posibilidad de tratar las excepciones que pudiese producirse al ejecutar asíncronamente el método atribuido, pues con ello llamar a EndInvoke() dejaría de relanzar la excepción producida.

    Por último, a modo de resumen a continuación se indican cuáles son los patrones que  pueden seguirse para recoger los resultados de una llamada asíncrona:

  1. Detectar si la llamada asíncrona ha finalizado mirando el valor de la propiedad IsComplete del objeto IAsyncResult devuelto por BeginInvoke() Cuando sea así, con EndInvoke() puede recogerse sus resultados.
  2. Pasar un objeto delegado en el penúltimo parámetro de BeginInvoke() con el método a ejecutar cuando finalice el hilo asíncrono, lo que liberaría al hilo llamante de la  tarea de tener que andar mirando si ha finalizado o no. 

    Si desde dicho método se necesitase acceder a los resultados del método llamado podría accederse a ellos a través de la propiedad AsyncDelegate del objeto IAsyncResult que recibe. Esta propiedad contiene el objeto delegado al que se llamó, aunque se muestra a continuación antes de acceder a ella hay que convertir el parámetro IAsyncResult de ese método en un AsyncResult:


public static void M(IAsyncResult iar)
{
 D objetoDelegado = (D) ((AsyncResult iar)).AsyncDelegate;
 // A partir de aquí podría llamarse a EndInvoke()
 // a través de objetoDelegado

}

 


Inicio | Tutorial C# La clase MulticastDelegateTutorial C#Implementación interna de los delegados Versión para imprimir Foros de consulta


Añadir comentario ... Para preguntar utiliza los foros
Autor:

Título:


Para preguntar utiliza los foros.



Inicio | Tutorial C# La clase MulticastDelegateTutorial C#Implementación interna de los delegados Versión para imprimir

Llamadas asíncronas
Autor: José Antonio González Seco
Visitas: 8328 Fecha de publicación: 19/10/2006
José Antonio es experto en tecnologias Microsoft. Imparte cursos y conferencias en congresos sobre C# y .NET en Universidades de toda España (Sevilla, Barcelona, San Sebastián, Valencia, Oviedo, etc.) en representación de grandes empresas como Microsoft.




Visitas: 132 | Comentarios: 0 | Archivo: Articulos
Categorias: Visual Basic .NET|C#|ASP.NET|ASP.NET|Programación|ADO.NET
27/09/2008 Navegando ....
Visitas: 56 | Comentarios: 0 | Archivo: Articulos
Categorias: Humor
Visitas: 172 | Comentarios: 0 | Archivo: Articulos
Categorias: Visual Basic .NET|C#|ASP.NET|ASP.NET|Programación|WCF
Visitas: 705 | Comentarios: 0 | Archivo: Articulos
Categorias: C#
Visitas: 176 | Comentarios: 0 | Archivo: Articulos
Categorias: JavaScript|ASP.NET
Visitas: 618 | Comentarios: 0 | Archivo: Articulos
Categorias: Windows XP|Linux|Windows Vista
Visitas: 404 | Comentarios: 0 | Archivo: Articulos
Categorias: Linux|BSD
Visitas: 213 | Comentarios: 0 | Archivo: Articulos
Categorias: Programación|Actualidad
18/08/2008 SQL Server 2008
Visitas: 1029 | Comentarios: 1 | Archivo: Articulos
Categorias: Transact-SQL
Visitas: 728 | Comentarios: 0 | Archivo: Articulos
Categorias: C#|ADO.NET|LinQ

Útimos temas recibidos en los foros ...
Crear una sesion de inicio por jhors ... [ASP.NET] 1 06/10/2008
Enviar email a correos cmo hotmail por Cajami ... [C#] 13 06/09/2007
Como mandar mensaje a Celular por Pako ... [C#] 23 13/03/2007
Casting por sara ... [Java] 1 06/10/2008
ORA-22288: file or LOB operation GetLength failed por heroga ... [ORACLE] 1 05/08/2008
Galeria de imagenes en Visual Web Developer por luis ... [ASP.NET] 0 06/10/2008
utilizar un ObjectDataSource por mari90 ... [ASP.NET] 4 25/10/2006
Llamar procedimientos almacenados por elmago ... [C#] 1 04/10/2008
Procesos huerfanos por cesarf283 ... [SQL Server] 2 11/07/2007
numero autogenerado por lucho ... [Visual Basic .NET] 17 10/01/2007
PUNTO DE VENTA por TIBURON ... [Access] 0 04/10/2008
Curso Visual Basic .NET en vídeo por martaz ... [Visual Basic .NET] 4 08/11/2007

Access CGI JSP ORACLE UNIX
Actualidad HTML/DHTML/XHTML LINUX PHP Visual Basic .NET
ASP ISAPI MS DOS Power Builder Visual Basic 6.0
ASP.NET Java mySQL SQL WIN 98/NT/2000/XP
C# JavaScript Opinion SQL Server

devjoker  Te recomendamos además ...
24/05/2006 Cursores Explicitos en PL/SQL    forma parte de...Tutorial PL/SQL
12/01/2008 SQL dinámico en Transact SQL    forma parte de...Tutorial de Transact SQL
07/11/2006 Enumeraciones    forma parte de...Tutorial C#
01/06/2007 Autogenerado ESSALUD (Solución)
11/03/2008 Problemas en la instalación de Visual Studio 2008-Visual studio web authoring component
28/08/2006 Ubuntu en VmWare con VMware Tools
24/07/2006 Transacciones autónomas    forma parte de...Tutorial PL/SQL
14/07/2007 Como encriptar texto y variables usando algoritmos estandard como DES o TRIPLEDES
22/10/2005 Vistas    forma parte de...Tutorial SQL
09/10/2006 Variables y tipos de datos    forma parte de...Tutorial C#

 

Encuesta
¿A que perfil te adaptas mejor?
[Ver] [Votar]