Chiamata asincrona dei metodi sincroniCalling Synchronous Methods Asynchronously

.NET Framework consente di chiamare qualsiasi metodo in modo asincrono.The .NET Framework enables you to call any method asynchronously. A questo scopo occorre definire un delegato con la stessa firma del metodo che si vuole chiamare. Common Language Runtime definisce automaticamente i metodi BeginInvoke e EndInvoke per il delegato, con le firme appropriate.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.

Nota

Le chiamate asincrone dei delegati, con particolare riferimento ai metodi BeginInvoke e EndInvoke , non sono supportate in .NET Compact Framework.Asynchronous delegate calls, specifically the BeginInvoke and EndInvoke methods, are not supported in the .NET Compact Framework.

Il BeginInvoke metodo avvia la chiamata asincrona.The BeginInvoke method initiates the asynchronous call. Presenta gli stessi parametri del metodo da eseguire in modo asincrono, con due parametri aggiuntivi facoltativi.It has the same parameters as the method that you want to execute asynchronously, plus two additional optional parameters. Il primo parametro è un delegato AsyncCallback che fa riferimento a un metodo da chiamare al completamento della chiamata asincrona.The first parameter is an AsyncCallback delegate that references a method to be called when the asynchronous call completes. Il secondo parametro è un oggetto definito dall'utente che passa informazioni al metodo di callback.The second parameter is a user-defined object that passes information into the callback method. BeginInvoke restituisce immediatamente un valore e non attende il completamento della chiamata asincrona.BeginInvoke returns immediately and does not wait for the asynchronous call to complete. BeginInvoke restituisce un oggetto IAsyncResultche può essere usato per monitorare lo stato di avanzamento della chiamata asincrona.BeginInvoke returns an IAsyncResult, which can be used to monitor the progress of the asynchronous call.

Il metodo EndInvoke recupera i risultati della chiamata asincrona.The EndInvoke method retrieves the results of the asynchronous call. Può essere chiamato in qualsiasi momento dopo BeginInvoke.It can be called any time after BeginInvoke. Se la chiamata asincrona non è stata completata, EndInvoke blocca il thread chiamante fino al suo completamento.If the asynchronous call has not completed, EndInvoke blocks the calling thread until it completes. Nei parametri di EndInvoke sono inclusi quelli di tipo out e ref (<Out> ByRef e ByRef in Visual Basic) del metodo da eseguire in modo asincrono, oltre all'oggetto IAsyncResult restituito da 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.

Nota

La funzionalità IntelliSense in Visual Studio 2005Visual Studio 2005 visualizza i parametri di BeginInvoke e EndInvoke.The IntelliSense feature in Visual Studio 2005Visual Studio 2005 displays the parameters of BeginInvoke and EndInvoke. Se non si usa Visual Studio o uno strumento analogo o se si usa C# con Visual Studio 2005Visual Studio 2005, vedere Asynchronous Programming Model (APM) (Modello di programmazione asincrona, APM) per una descrizione dei parametri definiti per tali metodi.If you are not using Visual Studio or a similar tool, or if you are using C# with Visual Studio 2005Visual Studio 2005, see Asynchronous Programming Model (APM) for a description of the parameters defined for these methods.

Gli esempi di codice in questo argomento presentano quattro modi comuni per usare BeginInvoke e EndInvoke per effettuare chiamate asincrone.The code examples in this topic demonstrate four common ways to use BeginInvoke and EndInvoke to make asynchronous calls. Dopo avere chiamato BeginInvoke è possibile procedere nel modo seguente:After calling BeginInvoke you can do the following:

  • Eseguire alcune operazioni, quindi chiamare EndInvoke per bloccare l'esecuzione fino al completamento della chiamata.Do some work and then call EndInvoke to block until the call completes.

  • Ottenere un oggetto WaitHandle con la proprietà IAsyncResult.AsyncWaitHandle, usare il relativo metodo WaitOne per bloccare l'esecuzione fino a quando non viene segnalato WaitHandle, quindi chiamare 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.

  • Eseguire il polling dell'oggetto IAsyncResult restituito da BeginInvoke per stabilire quando viene completata la chiamata, quindi chiamare EndInvoke.Poll the IAsyncResult returned by BeginInvoke to determine when the asynchronous call has completed, and then call EndInvoke.

  • Passare un delegato per un metodo di callback a BeginInvoke.Pass a delegate for a callback method to BeginInvoke. Il metodo viene eseguito su un thread ThreadPool al completamento della chiamata asincrona.The method is executed on a ThreadPool thread when the asynchronous call completes. Il metodo di callback chiama EndInvoke.The callback method calls EndInvoke.

Importante

Indipendentemente dalla tecnica usata, chiamare sempre EndInvoke per completare la chiamata asincrona.No matter which technique you use, always call EndInvoke to complete your asynchronous call.

Definizione del metodo di test e del delegato asincronoDefining the Test Method and Asynchronous Delegate

Gli esempi di codice seguenti illustrano diversi modi per chiamare lo stesso metodo di lunga durata, TestMethod, in modo asincrono.The code examples that follow demonstrate various ways of calling the same long-running method, TestMethod, asynchronously. Il metodo TestMethod visualizza un messaggio di console per indicare che ha iniziato l'elaborazione, si disattiva per alcuni secondi e quindi termina.The TestMethod method displays a console message to show that it has begun processing, sleeps for a few seconds, and then ends. TestMethod include un parametro out per dimostrare in che modo tali parametri vengono aggiunti alle firme di BeginInvoke e EndInvoke.TestMethod has an out parameter to demonstrate the way such parameters are added to the signatures of BeginInvoke and EndInvoke. I parametri ref possono essere gestiti in modo analogo.You can handle ref parameters similarly.

L'esempio di codice seguente illustra la definizione di TestMethod e il delegato denominato AsyncMethodCaller che può essere usato per chiamare TestMethod in modo asincrono.The following code example shows the definition of TestMethod and the delegate named AsyncMethodCaller that can be used to call TestMethod asynchronously. Per compilare gli esempi di codice, è necessario includere le definizioni per TestMethod e il delegato 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

Attesa di una chiamata asincrona con EndInvokeWaiting for an Asynchronous Call with EndInvoke

Il modo più semplice per eseguire un metodo in modo asincrono consiste nell'avviare l'esecuzione del metodo chiamando il metodo BeginInvoke del delegato, eseguire alcune operazioni sul thread principale e quindi chiamare il metodo EndInvoke del delegato.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 potrebbe bloccare il thread chiamante perché non restituisce un valore fino al completamento della chiamata asincrona.EndInvoke might block the calling thread because it does not return until the asynchronous call completes. Si tratta di una tecnica valida per le operazioni su file o rete.This is a good technique to use with file or network operations.

Importante

Poiché EndInvoke potrebbe bloccarsi, non deve mai essere chiamato dai thread che servono l'interfaccia utente.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.".

Attesa di una chiamata asincrona con WaitHandleWaiting for an Asynchronous Call with WaitHandle

È possibile ottenere un oggetto WaitHandle usando la proprietà AsyncWaitHandle dell'oggetto IAsyncResult restituito da BeginInvoke.You can obtain a WaitHandle by using the AsyncWaitHandle property of the IAsyncResult returned by BeginInvoke. L'oggetto WaitHandle viene segnalato al completamento della chiamata asincrona ed è possibile attenderlo chiamando il metodo WaitOne .The WaitHandle is signaled when the asynchronous call completes, and you can wait for it by calling the WaitOne method.

Se si usa un WaitHandle, è possibile eseguire altre operazioni prima o dopo il completamento della chiamata asincrona, ma prima di chiamare EndInvoke per recuperare i risultati.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.

Nota

L'handle di attesa non viene chiuso automaticamente quando si chiama EndInvoke.The wait handle is not closed automatically when you call EndInvoke. Se si rilasciano tutti i riferimenti all'handle di attesa, le risorse di sistema vengono liberate quando Garbage Collection recupera l'handle di attesa.If you release all references to the wait handle, system resources are freed when garbage collection reclaims the wait handle. Per liberare le risorse di sistema non appena si ha finito di usare l'handle di attesa, eliminarlo chiamando il metodo 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. Garbage Collection opera in modo più efficiente quando gli oggetti eliminabili vengono eliminati in modo esplicito.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.".

Polling del completamento della chiamata asincronaPolling for Asynchronous Call Completion

È possibile usare la proprietà IsCompleted dell'oggetto IAsyncResult restituito da BeginInvoke per rilevare il completamento della chiamata asincrona.You can use the IsCompleted property of the IAsyncResult returned by BeginInvoke to discover when the asynchronous call completes. Questa operazione può essere eseguita quando si effettua la chiamata asincrona da un thread che serve l'interfaccia utente.You might do this when making the asynchronous call from a thread that services the user interface. Il polling del completamento consente al thread chiamante di continuare l'esecuzione mentre viene eseguita la chiamata asincrona su 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.".

Esecuzione di un metodo di callback al completamento di una chiamata asincronaExecuting a Callback Method When an Asynchronous Call Completes

Se il thread che avvia la chiamata asincrona non deve necessariamente essere il thread che elabora i risultati, è possibile eseguire un metodo di callback al completamento della chiamata.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. Il metodo di callback viene eseguito su un thread ThreadPool .The callback method is executed on a ThreadPool thread.

Per usare un metodo di callback, è necessario passare a BeginInvoke un delegato AsyncCallback che rappresenta il metodo di callback.To use a callback method, you must pass BeginInvoke an AsyncCallback delegate that represents the callback method. È possibile passare anche un oggetto contenente informazioni che devono essere usate dal metodo di callback.You can also pass an object that contains information to be used by the callback method. Nel metodo di callback è possibile eseguire il cast di IAsyncResult, che è l'unico parametro del metodo di callback, a un oggetto AsyncResult .In the callback method, you can cast the IAsyncResult, which is the only parameter of the callback method, to an AsyncResult object. È quindi possibile usare la proprietà AsyncResult.AsyncDelegate per ottenere il delegato usato per avviare la chiamata in modo che sia possibile chiamare 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.

Note sull'esempio:Notes on the example:

  • Il parametro threadId di TestMethod è un parametro out ([<Out> ByRef in Visual Basic), quindi il valore di input non viene mai usato da TestMethod.The threadId parameter of TestMethod is an out parameter ([<Out> ByRef in Visual Basic), so its input value is never used by TestMethod. Viene passata una variabile fittizia alla chiamata BeginInvoke .A dummy variable is passed to the BeginInvoke call. Se il parametro threadId fosse un parametro ref (ByRef in Visual Basic), la variabile dovrebbe essere un campo a livello di classe perché possa essere passata sia a BeginInvoke che a 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.

  • Le informazioni sullo stato che vengono passate a BeginInvoke sono costituite da una stringa di formato, che viene usata dal metodo di callback per formattare un messaggio di output.The state information that is passed to BeginInvoke is a format string, which the callback method uses to format an output message. Dato che le informazioni sullo stato vengono passate come tipo Object, è necessario eseguirne il cast al tipo appropriato prima di poterle usare.Because it is passed as type Object, the state information must be cast to its proper type before it can be used.

  • Il callback viene eseguito su un thread ThreadPool .The callback is made on a ThreadPool thread. I threadThreadPool sono thread in background, che non mantengono l'applicazione in esecuzione se il thread principale termina, quindi il thread principale dell'esempio deve rimanere sospeso per un tempo sufficiente al completamento del callback.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.

Vedere ancheSee Also

Delegate
Event-based Asynchronous Pattern (EAP) (Modello asincrono basato su eventi, EAP)Event-based Asynchronous Pattern (EAP)