Le .NET Framework vous permet d'appeler n'importe quelle méthode de façon asynchrone. Pour ce faire, définissez un délégué possédant la même signature que la méthode à appeler ; le Common Language Runtime définit automatiquement les méthodes BeginInvoke et EndInvoke pour ce délégué avec les signatures appropriées.
La méthode BeginInvoke initialise l'appel asynchrone. Elle possède les mêmes paramètres que la méthode à exécuter de façon asynchrone, plus deux paramètres optionnels. Le premier paramètre est un délégué AsyncCallback qui fait référence à une méthode à appeler lorsque l'appel asynchrone se termine. Le deuxième paramètre est un objet défini par l'utilisateur qui passe les informations à la méthode de rappel. BeginInvoke retourne immédiatement une valeur et n'attend pas que l'appel asynchrone soit terminé. BeginInvoke retourne un IAsyncResult qui peut être utilisé pour surveiller la progression de l'appel asynchrone.
La méthode EndInvoke récupère les résultats de l'appel asynchrone. Elle peut être appelée à tout moment après la méthode BeginInvoke ; si l'appel asynchrone n'est pas terminé, la méthode EndInvoke bloque le thread appelant jusqu'à ce qu'il se termine. Les paramètres de la méthode EndInvoke incluent les paramètres out et ref (<Out> ByRef et ByRef en Visual Basic) de la méthode à exécuter de façon asynchrone, plus le IAsyncResult retourné par BeginInvoke.
Remarque |
|---|
| La fonctionnalité IntelliSense de Visual Studio 2005 affiche les paramètres des méthodes BeginInvoke et EndInvoke. Si vous n'utilisez ni Visual Studio ni un outil similaire, ou si vous utilisez C# avec Visual Studio 2005, consultez Vue d'ensemble de la programmation asynchrone pour une description des paramètres définis pour ces méthodes. |
Les exemples de code de cette rubrique illustrent quatre utilisations classiques des méthodes BeginInvoke et EndInvoke pour effectuer des appels asynchrones. Après un appel à BeginInvoke, vous pouvez effectuer les opérations suivantes :
-
travailler un moment, puis appeler EndInvoke pour que la méthode se bloque jusqu'à la fin de l'appel ;
-
obtenir un WaitHandle à l'aide de la propriété System.IAsyncResult.AsyncWaitHandle, utiliser sa méthode WaitOne pour bloquer l'exécution jusqu'à ce que le WaitHandle soit signalé, puis appeler EndInvoke ;
-
interroger le IAsyncResult retourné par BeginInvoke pour savoir à quel moment l'appel s'est terminé, puis appeler EndInvoke ;
-
passer un délégué d'une méthode de rappel à BeginInvoke. La méthode est exécutée sur un thread ThreadPool lorsque l'appel asynchrone se termine. La méthode de rappel appelle la méthode EndInvoke.
Important Appelez toujours EndInvoke pour terminer votre appel asynchrone.
Définition de la méthode de test et du délégué asynchrone
Les exemples de code suivants illustrent différentes façons d'appeler la même méthode longue, TestMethod, de façon asynchrone. La méthode TestMethod affiche un message sur la console pour indiquer que son traitement a commencé, se met en veille pendant quelques secondes, puis se termine. TestMethod possède un paramètre out pour illustrer la manière dont ces paramètres sont ajoutés aux signatures de BeginInvoke et EndInvoke. Vous pouvez gérer les paramètres ref de façon similaire.
L'exemple de code suivant illustre la définition de TestMethod et le délégué nommé AsyncMethodCaller qui peut être utilisé pour appeler TestMethod de façon asynchrone. Pour compiler l'un des exemples de code, vous devez inclure les définitions pour TestMethod et le délégué AsyncMethodCaller.
Imports System Imports System.Threading Imports System.Runtime.InteropServices Namespace Examples.AdvancedProgramming.AsynchronousOperations Public Class AsyncDemo ' The method to be executed asynchronously. Public Function TestMethod(ByVal callDuration As Integer, _ <Out> ByRef threadId As Integer) As String Console.WriteLine("Test method begins.") Thread.Sleep(callDuration) threadId = Thread.CurrentThread.ManagedThreadId() return String.Format("My call time was {0}.", callDuration.ToString()) End Function End Class ' The delegate must have the same signature as the method ' it will call asynchronously. Public Delegate Function AsyncMethodCaller(ByVal callDuration As Integer, _ <Out> ByRef threadId As Integer) As String End Namespace
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncDemo { // The method to be executed asynchronously. public string TestMethod(int callDuration, out int threadId) { Console.WriteLine("Test method begins."); Thread.Sleep(callDuration); threadId = Thread.CurrentThread.ManagedThreadId; return String.Format("My call time was {0}.", callDuration.ToString()); } } // The delegate must have the same signature as the method // it will call asynchronously. public delegate string AsyncMethodCaller(int callDuration, out int threadId); }
Attente d'un appel asynchrone avec EndInvoke
La façon la plus simple d'exécuter une méthode de manière asynchrone consiste à démarrer l'exécution de la méthode en appelant la méthode BeginInvoke du délégué, effectuer quelques opérations sur le thread principal, puis appeler la méthode EndInvoke du délégué. EndInvoke peut bloquer le thread appelant car il n'est pas retourné tant que l'appel asynchrone n'est pas terminé. Cette technique convient bien aux opérations de fichier ou de réseau, mais parce qu'elle bloque sur EndInvoke, il est déconseillé de l'appeler à partir de threads qui desservent l'interface utilisateur.
Imports System Imports System.Threading Imports System.Runtime.InteropServices Namespace Examples.AdvancedProgramming.AsynchronousOperations Public Class AsyncMain Shared Sub Main() ' The asynchronous method puts the thread id here. Dim threadId As Integer ' Create an instance of the test class. Dim ad As New AsyncDemo() ' Create the delegate. Dim caller As New AsyncMethodCaller(AddressOf ad.TestMethod) ' Initiate the asynchronous call. Dim result As IAsyncResult = caller.BeginInvoke(3000, _ threadId, Nothing, Nothing) Thread.Sleep(0) Console.WriteLine("Main thread {0} does some work.", _ Thread.CurrentThread.ManagedThreadId) ' Call EndInvoke to Wait for the asynchronous call to complete, ' and to retrieve the results. Dim returnValue As String = caller.EndInvoke(threadId, result) Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", _ threadId, returnValue) End Sub End Class End Namespace
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { public static void Main() { // The asynchronous method puts the thread id here. int threadId; // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null); Thread.Sleep(0); Console.WriteLine("Main thread {0} does some work.", Thread.CurrentThread.ManagedThreadId); // Call EndInvoke to wait for the asynchronous call to complete, // and to retrieve the results. string returnValue = caller.EndInvoke(out threadId, result); Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, returnValue); } } }
Attente d'un appel asynchrone avec WaitHandle
Vous pouvez obtenir un WaitHandle à l'aide de la propriété AsyncWaitHandle du IAsyncResult retourné par BeginInvoke. Le WaitHandle est signalé lorsque l'appel asynchrone se termine et vous pouvez l'attendre en appelant la méthode WaitOne.
Si vous utilisez WaitHandle, vous pouvez effectuer un traitement supplémentaire avant ou après la fin de l'appel asynchrone, mais avant d'appeler EndInvoke pour récupérer les résultats.
Imports System Imports System.Threading Imports System.Runtime.InteropServices Namespace Examples.AdvancedProgramming.AsynchronousOperations Public Class AsyncMain Shared Sub Main() ' The asynchronous method puts the thread id here. Dim threadId As Integer ' Create an instance of the test class. Dim ad As New AsyncDemo() ' Create the delegate. Dim caller As New AsyncMethodCaller(AddressOf ad.TestMethod) ' Initiate the asynchronous call. Dim result As IAsyncResult = caller.BeginInvoke(3000, _ threadId, Nothing, Nothing) Thread.Sleep(0) Console.WriteLine("Main thread {0} does some work.", _ Thread.CurrentThread.ManagedThreadId) ' Perform additional processing here and then ' wait for the WaitHandle to be signaled. result.AsyncWaitHandle.WaitOne() ' Call EndInvoke to retrieve the results. Dim returnValue As String = caller.EndInvoke(threadId, result) Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", _ threadId, returnValue) End Sub End Class End Namespace
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { static void Main() { // The asynchronous method puts the thread id here. int threadId; // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null); Thread.Sleep(0); Console.WriteLine("Main thread {0} does some work.", Thread.CurrentThread.ManagedThreadId); // Wait for the WaitHandle to become signaled. result.AsyncWaitHandle.WaitOne(); // Perform additional processing here. // Call EndInvoke to retrieve the results. string returnValue = caller.EndInvoke(out threadId, result); Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, returnValue); } } }
Interrogation de la fin d'un appel asynchrone
Vous pouvez utiliser la propriété IsCompleted du IAsyncResult retourné par BeginInvoke pour savoir à quel moment l'appel asynchrone s'est terminé. Vous pouvez effectuer cette opération lorsque vous établissez l'appel asynchrone à partir d'un thread desservant l'interface utilisateur. L'interrogation permet alors au thread appelant de continuer à s'exécuter pendant que l'appel asynchrone s'exécute sur un thread ThreadPool.
Imports System Imports System.Threading Imports System.Runtime.InteropServices Namespace Examples.AdvancedProgramming.AsynchronousOperations Public Class AsyncMain Shared Sub Main() ' The asynchronous method puts the thread id here. Dim threadId As Integer ' Create an instance of the test class. Dim ad As New AsyncDemo() ' Create the delegate. Dim caller As New AsyncMethodCaller(AddressOf ad.TestMethod) ' Initiate the asynchronous call. Dim result As IAsyncResult = caller.BeginInvoke(3000, _ threadId, Nothing, Nothing) ' Poll while simulating work. While result.IsCompleted = False Thread.Sleep(10) End While ' Call EndInvoke to retrieve the results. Dim returnValue As String = caller.EndInvoke(threadId, result) Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", _ threadId, returnValue) End Sub End Class End Namespace
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { static void Main() { // The asynchronous method puts the thread id here. int threadId; // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null); // Poll while simulating work. while(result.IsCompleted == false) { Thread.Sleep(10); } // Call EndInvoke to retrieve the results. string returnValue = caller.EndInvoke(out threadId, result); Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, returnValue); } } }
Exécution d'une méthode de rappel à la fin d'un appel asynchrone
Si le thread qui établit l'appel asynchrone n'a pas forcément besoin de traiter les résultats, vous pouvez exécuter une méthode de rappel lorsque l'appel se termine. La méthode de rappel est exécutée sur un thread ThreadPool.
Pour utiliser une méthode de rappel, vous devez passer à BeginInvoke un délégué AsyncCallback faisant référence à la méthode de rappel. Vous pouvez également passer un objet contenant des informations qui seront exploitées par la méthode de rappel. Par exemple, vous pouvez passer le délégué utilisé pour établir l'appel de sorte que la méthode de rappel puisse appeler EndInvoke.
Imports System Imports System.Threading Imports System.Runtime.InteropServices Namespace Examples.AdvancedProgramming.AsynchronousOperations Public Class AsyncMain ' The asynchronous method puts the thread id here. Private Shared threadId As Integer Shared Sub Main() ' Create an instance of the test class. Dim ad As New AsyncDemo() ' Create the delegate. Dim caller As New AsyncMethodCaller(AddressOf ad.TestMethod) ' Initiate the asynchronous call. Dim result As IAsyncResult = caller.BeginInvoke(3000, _ threadId, _ AddressOf CallbackMethod, _ caller) Console.WriteLine("Press Enter to close application.") Console.ReadLine() End Sub ' Callback method must have the same signature as the ' AsyncCallback delegate. Shared Sub CallbackMethod(ByVal ar As IAsyncResult) ' Retrieve the delegate. Dim caller As AsyncMethodCaller = CType(ar.AsyncState, AsyncMethodCaller) ' Call EndInvoke to retrieve the results. Dim returnValue As String = caller.EndInvoke(threadId, ar) Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", _ threadId, returnValue) End Sub End Class End Namespace
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { // Asynchronous method puts the thread id here. private static int threadId; static void Main() { // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. Include an AsyncCallback // delegate representing the callback method, and the data // needed to call EndInvoke. IAsyncResult result = caller.BeginInvoke(3000, out threadId, new AsyncCallback(CallbackMethod), caller ); Console.WriteLine("Press Enter to close application."); Console.ReadLine(); } // Callback method must have the same signature as the // AsyncCallback delegate. static void CallbackMethod(IAsyncResult ar) { // Retrieve the delegate. AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState; // Call EndInvoke to retrieve the results. string returnValue = caller.EndInvoke(out threadId, ar); Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, returnValue); } } }
Outils (masquer)
S'enregistrer
Liste des Membres
Qui est en ligne?
FAQ