Información general acerca del modelo de diseño asincrónico
Una de las innovaciones que proporciona el modelo asincrónico es que quien llama decide si una llamada determinada debe ser asincrónica. No es necesario realizar una programación adicional para que el objeto llamado admita el comportamiento asincrónico de sus clientes; los delegados asincrónicos se encargan de ello en el modelo. Common Language Runtime trata las diferencias entre las vistas del objeto que realiza la llamada y del objeto llamado. El objeto llamado puede optar por admitir explícitamente el comportamiento asincrónico, ya que puede implementar este comportamiento de forma más eficiente que con una arquitectura general o quizá sólo desee admitir el comportamiento asincrónico por parte de quienes llaman. Sin embargo, se recomienda que tales objetos llamados sigan el modelo de diseño asincrónico para exponer las operaciones asincrónicas.
La seguridad de tipos es otra innovación del modelo asincrónico. Para los delegados asincrónicos en particular, un compilador de lenguajes cuyo destino es .NET Framework y Common Language Runtime puede escribir firmas de método para las operaciones iniciales y finales que se asignen al método Invoke normal, por ejemplo, para BeginInvoke y EndInvoke. Esto es importante, ya que el compilador divide la llamada asincrónica en una operación inicial y otra final para el delegado asincrónico y permite que se pasen solamente parámetros válidos.
Las ideas básicas de este modelo son las siguientes:
- El que llama debe decidir si una determinada llamada debe ser asincrónica.
- El objeto llamado puede utilizar una programación adicional para admitir el comportamiento asincrónico de sus clientes, pero no es necesario. La infraestructura de Common Language Runtime debe ser capaz de tratar las diferencias entre las vistas del objeto que llama y el objeto llamado.
- El objeto llamado puede optar por admitir explícitamente el comportamiento asincrónico, ya que puede implementar este comportamiento de forma más eficiente que con una arquitectura general o quizá sólo desee admitir el comportamiento asincrónico por parte de quienes llaman. Sin embargo, se recomienda que tales objetos llamados sigan el modelo de diseño asincrónico para exponer las operaciones asincrónicas.
- El compilador genera firmas de métodos seguras para BeginInvoke y EndInvoke, para los delegados asincrónicos.
- .NET Framework proporciona los servicios necesarios para admitir el modelo de programación asincrónica. A continuación se muestra una lista parcial de ejemplos de estos servicios:
- Primitivas de sincronización, tales como supervisores y bloqueos de lectura y escritura.
- Subprocesos y sondeos de subprocesos.
- Construcciones de sincronización, como contenedores que sean compatibles con la espera en objetos.
- Exposición a la infraestructura subyacente, tales como objetos IMessage y sondeos de subprocesos.
El modelo divide una llamada asincrónica en partes: una operación inicial, una operación final y el objeto resultante. Consulte el siguiente ejemplo, en el que el método Factorize puede tardar mucho tiempo en completarse.
public class PrimeFactorizer
{
public bool Factorize(int factorizableNum, ref int primefactor1, ref int primefactor2)
{
// Determine whether factorizableNum is prime.
// If it is prime, return true. Otherwise, return false.
// If it is prime, place factors in primefactor1 and primefactor2.
}
}
Si se sigue el modelo asincrónico, el escritor de la biblioteca de clases agrega los métodos BeginFactorize y EndFactorize que dividen la operación sincrónica en dos operaciones asincrónicas:
public class PrimeFactorizer
{
public bool Factorize(
int factorizableNum,
ref int primefactor1,
ref int primefactor2)
{
// Determine whether factorizableNum is prime.
// if it is prime, return true; otherwise return false.
// if it is prime, place factors in primefactor1 and primefactor2
}
public IAsyncResult BeginFactorize(
int factorizableNum,
ref int primefactor1,
ref int primefactor2,
AsyncCallback callback,
Object state)
{
// Begin factoring asynchronously, and return a result object,
}
public bool EndFactorize(
ref int primefactor1,
ref int primefactor2,
IAsyncResult asyncResult
)
{
// End (or complete) the factorizing,
// return the results,
// and obtain the prime factors.
}
}
El servidor divide una operación asincrónica en dos partes lógicas: la parte que acepta la entrada del cliente e inicia la operación asincrónica y la parte que proporciona los resultados de la operación asincrónica al cliente.
Además de la entrada necesaria para la operación asincrónica, la primera parte también acepta un objeto delegado AsyncCallback que se llama después de completar la operación asincrónica. La primera parte devuelve un objeto temporizador de espera que implementa la interfaz IAsyncResult utilizada por el cliente para determinar el estado de la operación asincrónica.
El servidor también utiliza el objeto temporizador de espera que devolvió al cliente para mantener cualquier estado asociado con la operación asincrónica. El cliente utiliza la segunda parte para obtener los resultados de la operación asincrónica suministrando el objeto temporizador de espera.
Las opciones que tiene el cliente para iniciar operaciones asincrónicas son las siguientes:
Proporcionar el delegado de devolución de llamada al iniciar la llamada asincrónica.
public class Driver1 { public PrimeFactorizer primeFactorizer; public void Results(IAsyncResult asyncResult) { int primefactor1=0; int primefactor2=0; bool prime = primeFactorizer.EndFactorize( ref primefactor1, ref primefactor2, asyncResult); } public void Work() { int factorizableNum=1000589023, int primefactor1=0; int primefactor2=0; Object state = new Object(); primeFactorizer = new PrimeFactorizer(); AsyncCallback callback = new Callback(this.Results); IAsyncResult asyncResult = primeFactorizer.BeginFactorize( factorizableNum, ref primefactor1, ref primefactor2, callback, state); } }
No proporcionar el delegado de devolución de llamada al iniciar la operación asincrónica.
public class Driver2 { public static void Work() { int factorizableNum=1000589023, int primefactor1=0; int primefactor2=0; Object state = new Object(); PrimeFactorizer primeFactorizer = new PrimeFactorizer(); AsyncCallback callback = new Callback(this.Results); IAsyncResult asyncResult = primeFactorizer.BeginFactorize( factorizableNum, ref primefactor1, ref primefactor2, callback, state); bool prime = primeFactorizer.EndFactorize( ref primefactor1, ref primefactor2, asyncResult); } }
Vea también
Firmas de métodos asincrónicos | IAsyncResult (Interfaz) | Delegado AsyncCallback para operaciones asincrónicas | Programación asincrónica