Appel de méthodes synchrones de façon asynchroneCalling Synchronous Methods Asynchronously

Le .NET Framework vous permet d’appeler n’importe quelle méthode de façon asynchrone.The .NET Framework enables you to call any method asynchronously. Pour ce faire, vous définissez un délégué avec 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.To do this you define a delegate with the same signature as the method you want to call; the common language runtime automatically defines BeginInvoke and EndInvoke methods for this delegate, with the appropriate signatures.

Notes

Les appels de délégués asynchrones, en particulier les méthodes BeginInvoke et EndInvoke , ne sont pas pris en charge dans le .NET Compact Framework.Asynchronous delegate calls, specifically the BeginInvoke and EndInvoke methods, are not supported in the .NET Compact Framework.

La méthode BeginInvoke lance l’appel asynchrone.The BeginInvoke method initiates the asynchronous call. Elle possède les mêmes paramètres que la méthode que vous voulez exécuter de façon asynchrone, plus deux paramètres facultatifs supplémentaires.It has the same parameters as the method that you want to execute asynchronously, plus two additional optional parameters. Le premier paramètre est un délégué AsyncCallback qui fait référence à une méthode appelée à la fin de l’appel asynchrone.The first parameter is an AsyncCallback delegate that references a method to be called when the asynchronous call completes. Le deuxième paramètre est un objet défini par l’utilisateur qui transmet les informations dans la méthode de rappel.The second parameter is a user-defined object that passes information into the callback method. BeginInvoke retourne immédiatement et n’attend pas la fin de l’appel asynchrone.BeginInvoke returns immediately and does not wait for the asynchronous call to complete. BeginInvoke retourne un IAsyncResult, qui peut être utilisé pour surveiller la progression de l’appel asynchrone.BeginInvoke returns an IAsyncResult, which can be used to monitor the progress of the asynchronous call.

La méthode EndInvoke récupère les résultats de l’appel asynchrone.The EndInvoke method retrieves the results of the asynchronous call. Elle peut être appelée à tout moment après BeginInvoke.It can be called any time after BeginInvoke. Si l’appel asynchrone n’est pas terminé, EndInvoke bloque le thread appelant jusqu’à la fin.If the asynchronous call has not completed, EndInvoke blocks the calling thread until it completes. Les paramètres de EndInvoke sont notamment les paramètres out et ref (<Out> ByRef et ByRef en Visual Basic) de la méthode que vous voulez exécuter de façon asynchrone, plus le IAsyncResult retourné par BeginInvoke.The parameters of EndInvoke include the out and ref parameters (<Out> ByRef and ByRef in Visual Basic) of the method that you want to execute asynchronously, plus the IAsyncResult returned by BeginInvoke.

Notes

La fonctionnalité IntelliSense dans Visual Studio affiche les paramètres de BeginInvoke et EndInvoke.The IntelliSense feature in Visual Studio displays the parameters of BeginInvoke and EndInvoke. Si vous n’utilisez pas Visual Studio ou un outil similaire, ou si vous utilisez C# avec Visual Studio, consultez Modèle de programmation asynchrone pour une description des paramètres définis pour ces méthodes.If you're not using Visual Studio or a similar tool, or if you're using C# with Visual Studio, see Asynchronous Programming Model (APM) for a description of the parameters defined for these methods.

Les exemples de code de cette rubrique illustrent quatre façons courantes d’utiliser BeginInvoke et EndInvoke pour effectuer des appels asynchrones.The code examples in this topic demonstrate four common ways to use BeginInvoke and EndInvoke to make asynchronous calls. Vous pouvez effectuer les opérations suivantes après l’appel de BeginInvoke :After calling BeginInvoke you can do the following:

  • Effectuez quelques tâches, puis appelez EndInvoke pour bloquer l’exécution jusqu’à la fin de l’appel.Do some work and then call EndInvoke to block until the call completes.

  • Obtenez un WaitHandle à l’aide de la propriété IAsyncResult.AsyncWaitHandle , utilisez sa méthode WaitOne pour bloquer l’exécution jusqu’à ce que WaitHandle soit signalé, puis appelez EndInvoke.Obtain a WaitHandle using the IAsyncResult.AsyncWaitHandle property, use its WaitOne method to block execution until the WaitHandle is signaled, and then call EndInvoke.

  • Interrogez le IAsyncResult retourné par BeginInvoke pour déterminer quand l’appel asynchrone s’est terminé, puis appelez EndInvoke.Poll the IAsyncResult returned by BeginInvoke to determine when the asynchronous call has completed, and then call EndInvoke.

  • Passez un délégué d’une méthode de rappel à BeginInvoke.Pass a delegate for a callback method to BeginInvoke. La méthode est exécutée sur un thread ThreadPool à la fin de l’appel asynchrone.The method is executed on a ThreadPool thread when the asynchronous call completes. La méthode de rappel appelle EndInvoke.The callback method calls EndInvoke.

Important

Quelle que soit la technique utilisée, appelez toujours EndInvoke pour terminer votre appel asynchrone.No matter which technique you use, always call EndInvoke to complete your asynchronous call.

Définition de la méthode de test et du délégué asynchroneDefining the Test Method and Asynchronous Delegate

Les exemples de code suivants illustrent différentes façons d’appeler la même méthode longue, TestMethod, de façon asynchrone.The code examples that follow demonstrate various ways of calling the same long-running method, TestMethod, asynchronously. La méthode TestMethod affiche un message de console pour indiquer qu’elle a commencé le traitement, se met en veille pendant quelques secondes, puis se termine.The TestMethod method displays a console message to show that it has begun processing, sleeps for a few seconds, and then ends. TestMethod possède un paramètre out pour illustrer la façon dont ces paramètres sont ajoutés aux signatures de BeginInvoke et EndInvoke.TestMethod has an out parameter to demonstrate the way such parameters are added to the signatures of BeginInvoke and EndInvoke. Vous pouvez gérer les paramètres ref de la même façon.You can handle ref parameters similarly.

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 manière asynchrone.The following code example shows the definition of TestMethod and the delegate named AsyncMethodCaller that can be used to call TestMethod asynchronously. Pour compiler les exemples de code, vous devez inclure les définitions de TestMethod et le délégué AsyncMethodCaller .To compile the code examples, you must include the definitions for TestMethod and the AsyncMethodCaller delegate.

using namespace System;
using namespace System::Threading;
using namespace System::Runtime::InteropServices; 

namespace Examples {
namespace AdvancedProgramming {
namespace AsynchronousOperations
{
    public ref class AsyncDemo 
    {
    public:
        // The method to be executed asynchronously.
        String^ TestMethod(int callDuration, [OutAttribute] int% threadId) 
        {
            Console::WriteLine("Test method begins.");
            Thread::Sleep(callDuration);
            threadId = Thread::CurrentThread->ManagedThreadId;
            return String::Format("My call time was {0}.", callDuration);
        }
    };

    // The delegate must have the same signature as the method
    // it will call asynchronously.
    public delegate String^ AsyncMethodCaller(int callDuration, [OutAttribute] int% threadId);
}}}
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);
}
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

Attente d’un appel asynchrone avec EndInvokeWaiting for an Asynchronous Call with EndInvoke

Le moyen le plus simple d’exécuter une méthode de manière asynchrone est de démarrer l’exécution de la méthode en appelant la méthode BeginInvoke du délégué, d’effectuer quelques tâches sur le thread principal, puis d’appeler la méthode EndInvoke du délégué.The simplest way to execute a method asynchronously is to start executing the method by calling the delegate's BeginInvoke method, do some work on the main thread, and then call the delegate's EndInvoke method. EndInvoke peut bloquer le thread appelant, car il ne retourne de pas résultat avant la fin de l’appel asynchrone.EndInvoke might block the calling thread because it does not return until the asynchronous call completes. Cette technique est utile pour les opérations de fichier ou de réseau.This is a good technique to use with file or network operations.

Important

Étant donné que EndInvoke peut bloquer l’exécution, ne l’appelez jamais à partir de threads qui gèrent l’interface utilisateur.Because EndInvoke might block, you should never call it from threads that service the user interface.

#using <TestMethod.dll>

using namespace System;
using namespace System::Threading;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;

void main() 
{
    // The asynchronous method puts the thread id here.
    int threadId = 2546;

    // Create an instance of the test class.
    AsyncDemo^ ad = gcnew AsyncDemo();

    // Create the delegate.
    AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::TestMethod);
       
    // Initiate the asychronous call.
    IAsyncResult^ result = caller->BeginInvoke(3000, 
        threadId, nullptr, nullptr);

    Thread::Sleep(1);
    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(threadId, result);

    Console::WriteLine("The call executed on thread {0}, with return value \"{1}\".",
        threadId, returnValue);
}

/* This example produces output similar to the following:

Main thread 1 does some work.
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
 */
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);
        }
    }
}

/* This example produces output similar to the following:

Main thread 1 does some work.
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
 */
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

'This example produces output similar to the following:
'
'Main thread 1 does some work.
'Test method begins.
'The call executed on thread 3, with return value "My call time was 3000.".

Attente d’un appel asynchrone avec WaitHandleWaiting for an Asynchronous Call with WaitHandle

Vous pouvez obtenir un WaitHandle à l’aide de la propriété AsyncWaitHandle du IAsyncResult retourné par BeginInvoke.You can obtain a WaitHandle by using the AsyncWaitHandle property of the IAsyncResult returned by BeginInvoke. Le WaitHandle est signalé quand l’appel asynchrone se termine et vous pouvez l’attendre en appelant la méthode WaitOne .The WaitHandle is signaled when the asynchronous call completes, and you can wait for it by calling the WaitOne method.

Si vous utilisez un 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.If you use a WaitHandle, you can perform additional processing before or after the asynchronous call completes, but before calling EndInvoke to retrieve the results.

Notes

Le handle d’attente n’est pas fermé automatiquement quand vous appelez EndInvoke.The wait handle is not closed automatically when you call EndInvoke. Si vous libérez toutes les références au handle d’attente, les ressources système sont libérées quand le garbage collection récupère le handle d’attente.If you release all references to the wait handle, system resources are freed when garbage collection reclaims the wait handle. Pour libérer les ressources système dès que vous avez terminé d’utiliser le handle d’attente, supprimez-le en appelant la méthode WaitHandle.Close .To free the system resources as soon as you are finished using the wait handle, dispose of it by calling the WaitHandle.Close method. Le garbage collection fonctionne plus efficacement quand les objets à supprimer le sont explicitement.Garbage collection works more efficiently when disposable objects are explicitly disposed.

#using <TestMethod.dll>

using namespace System;
using namespace System::Threading;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;

void main() 
{
    // The asynchronous method puts the thread id here.
    int threadId;

    // Create an instance of the test class.
    AsyncDemo^ ad = gcnew AsyncDemo();

    // Create the delegate.
    AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::TestMethod);
       
    // Initiate the asychronous call.
    IAsyncResult^ result = caller->BeginInvoke(3000, 
        threadId, nullptr, nullptr);

    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(threadId, result);

    // Close the wait handle.
    result->AsyncWaitHandle->Close();

    Console::WriteLine("The call executed on thread {0}, with return value \"{1}\".",
        threadId, returnValue);
}

/* This example produces output similar to the following:

Main thread 1 does some work.
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
 */
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);

            // Close the wait handle.
            result.AsyncWaitHandle.Close();

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

/* This example produces output similar to the following:

Main thread 1 does some work.
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
 */
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)

            ' Close the wait handle.
            result.AsyncWaitHandle.Close()

            Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", _
                threadId, returnValue)
        End Sub
    End Class
End Namespace

'This example produces output similar to the following:
'
'Main thread 1 does some work.
'Test method begins.
'The call executed on thread 3, with return value "My call time was 3000.".

Interrogation pour connaître l’état d’avancement de l’appel asynchronePolling for Asynchronous Call Completion

Vous pouvez utiliser la propriété IsCompleted du IAsyncResult retourné par BeginInvoke pour déterminer la fin de l’appel asynchrone.You can use the IsCompleted property of the IAsyncResult returned by BeginInvoke to discover when the asynchronous call completes. Cela est possible quand vous effectuez l’appel asynchrone à partir d’un thread qui gère l’interface utilisateur.You might do this when making the asynchronous call from a thread that services the user interface. L’interrogation pour connaître l’état d’avancement permet au thread appelant de continuer à s’exécuter pendant que l’appel asynchrone s’exécute sur un thread ThreadPool .Polling for completion allows the calling thread to continue executing while the asynchronous call executes on a ThreadPool thread.

#using <TestMethod.dll>

using namespace System;
using namespace System::Threading;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;

void main() 
{
    // The asynchronous method puts the thread id here.
    int threadId;

    // Create an instance of the test class.
    AsyncDemo^ ad = gcnew AsyncDemo();

    // Create the delegate.
    AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::TestMethod);
       
    // Initiate the asychronous call.
    IAsyncResult^ result = caller->BeginInvoke(3000, 
        threadId, nullptr, nullptr);

    // Poll while simulating work.
    while(result->IsCompleted == false)
    {
        Thread::Sleep(250);
        Console::Write(".");
    }

    // Call EndInvoke to retrieve the results.
    String^ returnValue = caller->EndInvoke(threadId, result);

    Console::WriteLine("\nThe call executed on thread {0}, with return value \"{1}\".",
        threadId, returnValue);
}

/* This example produces output similar to the following:

Test method begins.
.............
The call executed on thread 3, with return value "My call time was 3000.".
 */
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(250);
                Console.Write(".");
            }

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("\nThe call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

/* This example produces output similar to the following:

Test method begins.
.............
The call executed on thread 3, with return value "My call time was 3000.".
 */
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(250)
                Console.Write(".")
            End While

            ' Call EndInvoke to retrieve the results.
            Dim returnValue As String = caller.EndInvoke(threadId, result)

            Console.WriteLine(vbCrLf & _
                "The call executed on thread {0}, with return value ""{1}"".", _
                threadId, returnValue)
        End Sub
    End Class
End Namespace

' This example produces output similar to the following:
'
'Test method begins.
'.............
'The call executed on thread 3, with return value "My call time was 3000.".

Exécution d’une méthode de rappel à la fin d’un appel asynchroneExecuting a Callback Method When an Asynchronous Call Completes

Si le thread qui lance l’appel asynchrone ne doit pas nécessairement être le thread qui traite les résultats, vous pouvez exécuter une méthode de rappel à la fin de l’appel.If the thread that initiates the asynchronous call does not need to be the thread that processes the results, you can execute a callback method when the call completes. La méthode de rappel est exécutée sur un thread ThreadPool .The callback method is executed on a ThreadPool thread.

Pour utiliser une méthode de rappel, vous devez transmettre BeginInvoke et le délégué AsyncCallback qui représente la méthode de rappel.To use a callback method, you must pass BeginInvoke an AsyncCallback delegate that represents the callback method. Vous pouvez également transmettre un objet contenant les informations que la méthode de rappel doit utiliser.You can also pass an object that contains information to be used by the callback method. Dans la méthode de rappel, vous pouvez convertir le IAsyncResult, qui est le seul paramètre de la méthode de rappel, en objet AsyncResult .In the callback method, you can cast the IAsyncResult, which is the only parameter of the callback method, to an AsyncResult object. Vous pouvez ensuite utiliser la propriété AsyncResult.AsyncDelegate pour obtenir le délégué utilisé pour lancer l’appel, afin de pouvoir appeler EndInvoke.You can then use the AsyncResult.AsyncDelegate property to get the delegate that was used to initiate the call so that you can call EndInvoke.

Remarques sur l’exemple :Notes on the example:

  • Le paramètre threadId de TestMethod est un paramètre out (<Out> ByRef en Visual Basic). Sa valeur d’entrée n’est donc jamais utilisée par TestMethod.The threadId parameter of TestMethod is an out parameter ([<Out> ByRef in Visual Basic), so its input value is never used by TestMethod. Une variable factice est transmise à l’appel BeginInvoke .A dummy variable is passed to the BeginInvoke call. Si le paramètre threadId était un paramètre ref (ByRef en Visual Basic), la variable doit être un champ de niveau classe pour pouvoir être transmise à BeginInvoke et EndInvoke.If the threadId parameter were a ref parameter (ByRef in Visual Basic), the variable would have to be a class-level field so that it could be passed to both BeginInvoke and EndInvoke.

  • Les informations d’état transmises à BeginInvoke sont une chaîne de format, que la méthode de rappel utilise pour mettre en forme un message de sortie.The state information that is passed to BeginInvoke is a format string, which the callback method uses to format an output message. Parce qu’elles sont transmises en tant que type Object, les informations d’état doivent être converties en leur propre type avant de pouvoir être utilisées.Because it is passed as type Object, the state information must be cast to its proper type before it can be used.

  • Le rappel est effectué sur un thread ThreadPool .The callback is made on a ThreadPool thread. Les threadsThreadPool sont des threads d’arrière-plan qui arrêtent l’exécution de l’application si le thread principal s’arrête. Ainsi, le thread principal de l’exemple doit se mettre en veille suffisamment longtemps pour que le rappel puisse se terminer.ThreadPool threads are background threads, which do not keep the application running if the main thread ends, so the main thread of the example has to sleep long enough for the callback to finish.

#using <TestMethod.dll>

using namespace System;
using namespace System::Threading;
using namespace System::Runtime::Remoting::Messaging;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;

// The callback method must have the same signature as the
// AsyncCallback delegate.
void CallbackMethod(IAsyncResult^ ar) 
{
    // Retrieve the delegate.
    AsyncResult^ result = (AsyncResult^) ar;
    AsyncMethodCaller^ caller = (AsyncMethodCaller^) result->AsyncDelegate;

    // Retrieve the format string that was passed as state 
    // information.
    String^ formatString = (String^) ar->AsyncState;

    // Define a variable to receive the value of the out parameter.
    // If the parameter were ref rather than out then it would have to
    // be a class-level field so it could also be passed to BeginInvoke.
    int threadId = 0;

    // Call EndInvoke to retrieve the results.
    String^ returnValue = caller->EndInvoke(threadId, ar);

    // Use the format string to format the output message.
    Console::WriteLine(formatString, threadId, returnValue);
};

void main() 
{
    // Create an instance of the test class.
    AsyncDemo^ ad = gcnew AsyncDemo();

    // Create the delegate.
    AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::TestMethod);
       
    // The threadId parameter of TestMethod is an out parameter, so
    // its input value is never used by TestMethod. Therefore, a dummy
    // variable can be passed to the BeginInvoke call. If the threadId
    // parameter were a ref parameter, it would have to be a class-
    // level field so that it could be passed to both BeginInvoke and 
    // EndInvoke.
    int dummy = 0;

    // Initiate the asynchronous call, passing three seconds (3000 ms)
    // for the callDuration parameter of TestMethod; a dummy variable 
    // for the out parameter (threadId); the callback delegate; and
    // state information that can be retrieved by the callback method.
    // In this case, the state information is a string that can be used
    // to format a console message.
    IAsyncResult^ result = caller->BeginInvoke(3000,
        dummy, 
        gcnew AsyncCallback(&CallbackMethod),
        "The call executed on thread {0}, with return value \"{1}\".");

    Console::WriteLine("The main thread {0} continues to execute...", 
        Thread::CurrentThread->ManagedThreadId);

    // The callback is made on a ThreadPool thread. ThreadPool threads
    // are background threads, which do not keep the application running
    // if the main thread ends. Comment out the next line to demonstrate
    // this.
    Thread::Sleep(4000);
    Console::WriteLine("The main thread ends.");
}

/* This example produces output similar to the following:

The main thread 1 continues to execute...
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
The main thread ends.
 */
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        static void Main() 
        {
            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
       
            // The threadId parameter of TestMethod is an out parameter, so
            // its input value is never used by TestMethod. Therefore, a dummy
            // variable can be passed to the BeginInvoke call. If the threadId
            // parameter were a ref parameter, it would have to be a class-
            // level field so that it could be passed to both BeginInvoke and 
            // EndInvoke.
            int dummy = 0;

            // Initiate the asynchronous call, passing three seconds (3000 ms)
            // for the callDuration parameter of TestMethod; a dummy variable 
            // for the out parameter (threadId); the callback delegate; and
            // state information that can be retrieved by the callback method.
            // In this case, the state information is a string that can be used
            // to format a console message.
            IAsyncResult result = caller.BeginInvoke(3000,
                out dummy, 
                new AsyncCallback(CallbackMethod),
                "The call executed on thread {0}, with return value \"{1}\".");

            Console.WriteLine("The main thread {0} continues to execute...", 
                Thread.CurrentThread.ManagedThreadId);

            // The callback is made on a ThreadPool thread. ThreadPool threads
            // are background threads, which do not keep the application running
            // if the main thread ends. Comment out the next line to demonstrate
            // this.
            Thread.Sleep(4000);

            Console.WriteLine("The main thread ends.");
        }
        
        // The callback method must have the same signature as the
        // AsyncCallback delegate.
        static void CallbackMethod(IAsyncResult ar) 
        {
            // Retrieve the delegate.
            AsyncResult result = (AsyncResult) ar;
            AsyncMethodCaller caller = (AsyncMethodCaller) result.AsyncDelegate;

            // Retrieve the format string that was passed as state 
            // information.
            string formatString = (string) ar.AsyncState;

            // Define a variable to receive the value of the out parameter.
            // If the parameter were ref rather than out then it would have to
            // be a class-level field so it could also be passed to BeginInvoke.
            int threadId = 0;

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, ar);

            // Use the format string to format the output message.
            Console.WriteLine(formatString, threadId, returnValue);
        }
    }
}

/* This example produces output similar to the following:

The main thread 1 continues to execute...
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
The main thread ends.
 */
Imports System
Imports System.Threading
Imports System.Runtime.Remoting.Messaging

Namespace Examples.AdvancedProgramming.AsynchronousOperations

    Public Class AsyncMain 
        
        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)

            ' The threadId parameter of TestMethod is an <Out> parameter, so
            ' its input value is never used by TestMethod. Therefore, a dummy
            ' variable can be passed to the BeginInvoke call. If the threadId
            ' parameter were a ByRef parameter, it would have to be a class-
            ' level field so that it could be passed to both BeginInvoke and 
            ' EndInvoke.
            Dim dummy As Integer = 0

            ' Initiate the asynchronous call, passing three seconds (3000 ms)
            ' for the callDuration parameter of TestMethod; a dummy variable 
            ' for the <Out> parameter (threadId); the callback delegate; and
            ' state information that can be retrieved by the callback method.
            ' In this case, the state information is a string that can be used
            ' to format a console message.
            Dim result As IAsyncResult = caller.BeginInvoke(3000, _
                dummy, _
                AddressOf CallbackMethod, _
                "The call executed on thread {0}, with return value ""{1}"".")

            Console.WriteLine("The main thread {0} continues to execute...", _
                Thread.CurrentThread.ManagedThreadId)

            ' The callback is made on a ThreadPool thread. ThreadPool threads
            ' are background threads, which do not keep the application running
            ' if the main thread ends. Comment out the next line to demonstrate
            ' this.
            Thread.Sleep(4000)

            Console.WriteLine("The main thread ends.")
        End Sub

        ' The callback method must have the same signature as the
        ' AsyncCallback delegate.
        Shared Sub CallbackMethod(ByVal ar As IAsyncResult)
            ' Retrieve the delegate.
            Dim result As AsyncResult = CType(ar, AsyncResult)
            Dim caller As AsyncMethodCaller = CType(result.AsyncDelegate, AsyncMethodCaller)

            ' Retrieve the format string that was passed as state 
            ' information.
            Dim formatString As String = CType(ar.AsyncState, String)

            ' Define a variable to receive the value of the <Out> parameter.
            ' If the parameter were ByRef rather than <Out> then it would have to
            ' be a class-level field so it could also be passed to BeginInvoke.
            Dim threadId As Integer = 0

            ' Call EndInvoke to retrieve the results.
            Dim returnValue As String = caller.EndInvoke(threadId, ar)

            ' Use the format string to format the output message.
            Console.WriteLine(formatString, threadId, returnValue)
        End Sub
    End Class
End Namespace

' This example produces output similar to the following:
'
'The main thread 1 continues to execute...
'Test method begins.
'The call executed on thread 3, with return value "My call time was 3000.".
'The main thread ends.

Voir aussiSee also