Cómo llamar a un método de C# de forma asincrónica

Seleccione idioma Seleccione idioma
Id. de artículo: 315582 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

Microsoft .NET Framework facilita la tarea llamar a funciones de forma asincrónica. Llamar a funciones de forma asincrónica hace que el sistema ejecutarlas en segundo plano en un subproceso secundario mientras continúa la función de llamada realizar otro trabajo. En una llamada de función (sincrónico) típico, se ejecuta inmediatamente la función en el mismo subproceso que hizo la llamada. La función de llamada espera a que se complete la llamada y recibe los resultados de la llamada antes de continuar. Por el contrario, cuando se realiza una llamada asincrónica, recuperar los resultados de la llamada asincrónica más adelante. En este artículo se muestra cómo hacerlo mediante C#.

Requisitos


En la lista siguiente se describe el hardware, el software, la infraestructura de red y los Service Packs recomendados que necesitará:
  • Microsoft Windows 2000 o Microsoft Windows XP o Microsoft Windows Server 2003
  • Visual Studio .NET o Visual Studio 2005
En este artículo se supone que está familiarizado con los temas siguientes:
  • Llamar a métodos en Visual C#
  • Cómo utilizar delegados

Cómo realizar llamadas asincrónicas

Llamadas asincrónicas se realizan mediante delegados. Un delegado es un objeto que contiene una función. Los delegados proporcionan una función sincrónica y también proporcionan métodos para llamar a la función ajustada de forma asincrónica. Estos métodos son BeginInvoke() y EndInvoke() . Las listas de parámetros de estos métodos varían en función de la firma de la función que ajusta el delegado. Tenga en cuenta que Visual Studio característica IntelliSense de .NET no muestra BeginInvoke() y EndInvoke() , por lo que no ver aparezcan en la función listas mientras escribe.

BeginInvoke() se utiliza para iniciar la llamada asincrónica. Tiene los mismos parámetros que la función ajustado, además de dos parámetros adicionales que se describirán más adelante en este artículo. BeginInvoke() regresa inmediatamente y no espera a que se complete la llamada asincrónica. BeginInvoke() devuelve un objeto IAsyncResult .

La función EndInvoke() se utiliza para recuperar los resultados de la llamada asincrónica. Puede llamarse en cualquier momento después BeginInvoke() . Si la llamada asincrónica no ha finalizado todavía, EndInvoke() bloques hasta que se complete. Los parámetros de la función EndInvoke() incluye la out y los parámetros ref que tiene la función ajustada y el objeto IAsyncResult devuelto por BeginInvoke() .

El siguiente es un ejemplo de un delegado y sus métodos BeginInvoke() y EndInvoke() :
// The following delegate 
delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;

// will have the following BeginInvoke() and EndInvoke methods:
IAsyncResult MethodDelegate.BeginInvoke(int iCallTime, out int iExecThread, AsyncCallback cb, object AsyncState); 

string MethodDelegate.EndInvoke (out int iExecThread, IAsyncResult ar) ;
				
hay cuatro formas comunes de utilizar BeginInvoke() y EndInvoke() para realizar llamadas asincrónicas. Después de llamar a BeginInvoke() , puede:
  • Opcionalmente, realizar algunas otras tareas y después utilice EndInvoke() .
  • Obtener un WaitHandle suministrada por el objeto IAsyncResult , utilizar su método WaitOne para bloquear hasta que se señalice WaitHandle y, a continuación, llamar a EndInvoke() .
  • Sondee el objeto IAsyncResult para determinar una vez finalizada la llamada asincrónica y, a continuación, llamar al EndInvoke() .
  • Que el sistema llama a una función de devolución de llamada que especifique. Esta función de devolución de llamada llama a EndInvoke() y procesa los resultados de la llamada asincrónica cuando finaliza.
Los ejemplos de código siguientes muestran estos patrones de llamada y el contraste con realizar una llamada sincrónica mediante la siguiente función:
string LongRunningMethod (int iCallTime, out int iExecThread)
{
	Thread.Sleep (iCallTime) ;
	iExecThread = AppDomain.GetCurrentThreadId ();
	return "MyCallTime was " + iCallTime.ToString() ;
}

				
LongRunningMethod() simula una función que se ejecuta durante mucho tiempo por en el modo de suspensión. Devuelve la hora de suspensión y el identificador del subproceso que se ejecuta. Si se llama asincrónicamente, encontrará que el ID de subproceso del subproceso en ejecución es distinto del el subproceso de llamada.

El primer paso es definir el delegado que englobe la función:
delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;
				

Ejemplo 1: Llamar A un método de forma sincrónica

Este ejemplo demuestra cómo llamar a LongRunningMethod() sincrónicamente mediante un delegado MethodDelegate . Los demás ejemplos Contraste esto haciendo llamadas de forma asincrónica.
  1. Inicie Microsoft Visual Studio .NET o Microsoft Visual Studio 2005.
  2. Cree un nuevo proyecto de aplicación de consola de Visual C# denominado AsyncDemo.
  3. Agregue una clase denominada AsyncDemo que está definido como se indica a continuación para el proyecto en un nuevo archivo .cs:
    using System;
    using System.Threading ; 
    using System.Windows.Forms ;
    
    public class AsyncDemo
    {
    	string LongRunningMethod (int iCallTime, out int iExecThread)
    	{
    		Thread.Sleep (iCallTime) ;
    		iExecThread = AppDomain.GetCurrentThreadId ();
    		return "MyCallTime was " + iCallTime.ToString() ;
    	}
    
    	delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;
    
    	public void DemoSyncCall()
    	{
    		string s ;
    		int iExecThread;
    
    		// Create an instance of a delegate that wraps LongRunningMethod.
    		MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;  
    			
    		// Call LongRunningMethod using the delegate.
    		s = dlgt(3000, out iExecThread);  
    			
    		MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                            and the thread ID {1}", s, iExecThread.ToString() ) );
    	}
    }
    					
    más tarde, esta clase muestra cómo realizar llamadas asincrónicas. Inicialmente, sin embargo, sólo contiene el método DemoSyncCall() , que demuestra cómo llamar al delegado sincrónicamente.
  4. Agregue el código siguiente en el cuerpo de la función Main que Visual Studio crea automáticamente en el proyecto:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoSyncCall() ;
    }
    					
  5. Presione CTRL+F5 para ejecutar la aplicación.

Ejemplo 2: Llamada A método asincrónica utilizando el modelo de llamada EndInvoke()

En esta sección, el ejemplo invoca el método mismo de forma asincrónica. El patrón de llamada que se utiliza es llamar a BeginInvoke , realizar algo de trabajo en el subproceso principal y, a continuación, llamar a EndInvoke() . Tenga en cuenta que EndInvoke() no se devuelve hasta que finalice la llamada asincrónica. Este patrón de llamada es útil cuando desea que el subproceso de llamada trabajar el mismo tiempo que se está ejecutando la llamada asincrónica. Necesidad de trabajo que se producen al mismo tiempo, puede mejorar el rendimiento de muchas aplicaciones. Tareas comunes para ejecutar de forma asincrónica de este modo son operaciones de archivo o la red.
  1. Agregue un método denominado DemoEndInvoke() a la clase AsyncDemo . La función DemoEndInvoke muestra cómo llamar al delegado asincrónica.
    public void DemoEndInvoke()
    {
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    	string s ;
    	int iExecThread;
    
    	// Initiate the asynchronous call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);  
    
    	// Do some useful work here. This would be work you want to have
    	// run at the same time as the asynchronous call.
    
    	// Retrieve the results of the asynchronous call.
    	s = dlgt.EndInvoke (out iExecThread, ar) ;  
    
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                   and the number {1}", s, iExecThread.ToString() ) );
    }
    					
  2. Editar el código fuente para el principal para que contenga el siguiente código:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoEndInvoke() ;
    }
    					
  3. Presione CTRL+F5 para ejecutar la aplicación.

Ejemplo 3: Llamar A un método asincrónicamente y utilizando un WaitHandle para esperar la llamada para completar


En esta sección, el ejemplo llama al método asincrónicamente y espera un WaitHandle antes de llamar al EndInvoke() . El IAsyncResult devuelto por BeginInvoke() tiene una propiedad AsyncWaitHandle . Esta propiedad devuelve un WaitHandle se señaliza cuando finaliza la llamada asincrónica. Esperar en WaitHandle es una técnica de sincronización de subproceso común. El subproceso de llamada espera el WaitHandle utilizando el método WaitOne() de WaitHandle . WaitOne() se bloquea hasta que se señalice WaitHandle . Cuando devuelve WaitOne() , puede realizar algún trabajo adicional antes de llamar a EndInvoke() . Como en el ejemplo anterior, esta técnica es útil para ejecutar operaciones de archivo o de redes que de lo contrario bloquearía el subproceso principal llamado.
  1. Agregar una función denominada DemoWaitHandle() a la clase AsyncDemo . La función DemoWaitHandle() muestra cómo llamar al delegado asincrónica.
    public void DemoWaitHandle ()
    {
    	string s ;
    	int iExecThread;
    
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    
    	// Initiate the asynchronous call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null); 
    
    	// Do some useful work here. This would be work you want to have
    	// run at the same time as the asynchronous call.
    
    	// Wait for the WaitHandle to become signaled.
    	ar.AsyncWaitHandle.WaitOne() ;
    
    	// Get the results of the asynchronous call.
    	s = dlgt.EndInvoke (out iExecThread, ar) ;
    			
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                     and the number {1}", s, iExecThread.ToString() ) );
    }
    					
  2. Editar el código fuente para el principal para que contenga el siguiente código:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoWaitHandle () ;
    }
    					
  3. Presione CTRL+F5 para ejecutar la aplicación.

Ejemplo 4: Llamada A método asincrónica utilizando el modelo de llamadas de sondeo

En esta sección, el ejemplo sondea el objeto IAsyncResult para averiguar una vez finalizada la llamada asincrónica. El objeto IAsyncResult devuelto por BeginInvoke() tiene una propiedad IsCompleted devuelve true una vez finalizada la llamada asincrónica. Puede llamar a EndInvoke() . Este patrón de llamada es útil si la aplicación funciona continuo que no desee han bloqueadas por una llamada de función de ejecución prolongada. Una aplicación de Microsoft Windows es un ejemplo de esto. El subproceso principal de la aplicación de Windows puede continúan controlando los datos proporcionados por el usuario mientras se ejecuta una llamada asincrónica. Periódicamente, puede comprobar IsCompleted para ver si la llamada ha finalizado. Llama a EndInvoke IsCompleted devuelve true . Porque EndInvoke() se bloquea hasta que finalice la operación asincrónica, la aplicación no llama a él hasta que sepa que la operación es completa.
  1. Agregar una función denominada DemoPolling() a la clase AsyncDemo . La función DemoPolling() muestra cómo llamar al delegado asincrónica y utilizar el sondeo para ver si el proceso es completado.
    public void DemoPolling()
    {
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    	string s ;
    	int iExecThread;
    
    	// Initiate the asynchronous call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null); 
    
    	// Poll IAsyncResult.IsCompleted
    	while(ar.IsCompleted == false)
    	{
    		Thread.Sleep (10) ;  // pretend to so some useful work
    	}
    	s = dlgt.EndInvoke (out iExecThread, ar) ;
    
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                    and the number {1}", s, iExecThread.ToString() ) );
    }
    
    					
  2. Edite el código fuente para Main . Reemplace el contenido de la función con el siguiente código:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoPolling () ;
    }
    					
  3. Presione CTRL+F5 para ejecutar la aplicación.

Ejemplo 5: Ejecutar una devolución de llamada cuando se completa un método asincrónico

En esta sección, el ejemplo proporciona un delegado de devolución de llamada para la función BeginInvoke() que el sistema se ejecuta cuando finaliza la llamada asincrónica. La devolución de llamada llama al método EndInvoke() y procesa los resultados de la llamada asincrónica. Este patrón de llamada es útil si el subproceso que inicia la llamada asincrónica no necesita procesar los resultados de la llamada. El sistema invoca la devolución de llamada en un subproceso distinto al subproceso inicial cuando finaliza la llamada asincrónica.

Para utilizar este patrón de llamada, debe pasar a un delegado de tipo AsyncCallback como parámetro de la función BeginInvoke() segundo a último. BeginInvoke() tiene también un parámetro final de tipo de objeto en el que puede pasar cualquier objeto. Este objeto está disponible para la función de devolución de llamada cuando se invoca. Un uso importante de este parámetro es pasar el delegado que se utiliza para iniciar la llamada. La función de devolución de llamada podrá utilizar la función EndInvoke() de ese delegado para completar la llamada. Este patrón de llamada se muestra debajo.
  1. Agregar un dos métodos denominados DemoCallback() y MyAsyncCallback() a la clase AsyncDemo . El método DemoCallback() muestra cómo llamar al delegado asincrónica. Un delegado utiliza para ajustar el método MyAsyncCallback() , que el sistema llama a cuando finaliza la operación asincrónica. MyAsyncCallback() llama EndInvoke() .
    public void DemoCallback()
    {
    	MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    	string s ;
    	int iExecThread;
    
    	// Create the callback delegate.
    	AsyncCallback cb = new AsyncCallback(MyAsyncCallback);
    
    	// Initiate the Asynchronous call passing in the callback delegate
    	// and the delegate object used to initiate the call.
    	IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, cb, dlgt); 
    }
    
    public void MyAsyncCallback(IAsyncResult ar)
    {
    	string s ;
    	int iExecThread ;
    
    	// Because you passed your original delegate in the asyncState parameter
    	// of the Begin call, you can get it back here to complete the call.
    	MethodDelegate dlgt = (MethodDelegate) ar.AsyncState;
    
    	// Complete the call.
    	s = dlgt.EndInvoke (out iExecThread, ar) ;
    
    	MessageBox.Show (string.Format ("The delegate call returned the string:   \"{0}\", 
                                    and the number {1}", s, iExecThread.ToString() ) );
    }
    
    					
  2. Edite el código fuente para Main . Reemplace el contenido de la función con el siguiente código:
    static void Main(string[] args)
    {
    	AsyncDemo ad = new AsyncDemo () ;
    	ad.DemoCallback() ;
    }
    					
  3. Presione CTRL+F5 para ejecutar la aplicación.

Propiedades

Id. de artículo: 315582 - Última revisión: lunes, 11 de diciembre de 2006 - Versión: 4.3
La información de este artículo se refiere a:
  • Microsoft Visual Studio .NET 2002 Professional
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft Visual C# 2005 Express Edition
Palabras clave: 
kbmt kbhowtomaster KB315582 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 315582

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com