Synchrone methoden asynchroon aanroepen
Met .NET kunt u elke methode asynchroon aanroepen. Hiervoor definieert u een gemachtigde met dezelfde handtekening als de methode die u wilt aanroepen. De algemene taalruntime definieert BeginInvoke
en EndInvoke
methoden voor deze gemachtigde automatisch met de juiste handtekeningen.
Notitie
Asynchrone gemachtigdenaanroepen, met name de BeginInvoke
en EndInvoke
methoden, worden niet ondersteund in het .NET Compact Framework.
De BeginInvoke
methode initieert de asynchrone aanroep. Het heeft dezelfde parameters als de methode die u asynchroon wilt uitvoeren, plus twee extra optionele parameters. De eerste parameter is een AsyncCallback gemachtigde die verwijst naar een methode die moet worden aangeroepen wanneer de asynchrone aanroep is voltooid. De tweede parameter is een door de gebruiker gedefinieerd object dat informatie doorgeeft aan de callback-methode. BeginInvoke
retourneert onmiddellijk en wacht niet tot de asynchrone aanroep is voltooid. BeginInvoke
retourneert een IAsyncResult, die kan worden gebruikt om de voortgang van de asynchrone aanroep te controleren.
De EndInvoke
methode haalt de resultaten van de asynchrone aanroep op. Het kan op elk gewenst moment worden aangeroepen na BeginInvoke
. Als de asynchrone aanroep niet is voltooid, EndInvoke
blokkeert u de aanroepende thread totdat deze is voltooid. De parameters omvatten EndInvoke
de out
en ref
parameters (<Out>
ByRef
en ByRef
in Visual Basic) van de methode die u asynchroon wilt uitvoeren, plus de IAsyncResult geretourneerde door BeginInvoke
.
Notitie
Met de functie IntelliSense in Visual Studio worden de parameters van BeginInvoke
en EndInvoke
. Als u Visual Studio of een vergelijkbaar hulpprogramma niet gebruikt, of als u C# gebruikt met Visual Studio, raadpleegt u Asynchroon programmeermodel (APM) voor een beschrijving van de parameters die voor deze methoden zijn gedefinieerd.
De codevoorbeelden in dit onderwerp laten vier veelvoorkomende manieren zien om te gebruiken BeginInvoke
en EndInvoke
asynchrone aanroepen uit te voeren. Nadat u hebt gebeld BeginInvoke
, kunt u het volgende doen:
Doe wat werk en roep
EndInvoke
vervolgens aan om te blokkeren totdat het gesprek is voltooid.Haal een WaitHandle met behulp van de IAsyncResult.AsyncWaitHandle eigenschap op, gebruik de WaitOne methode om de uitvoering te blokkeren totdat het WaitHandle wordt gesignaleerd en roep vervolgens aan
EndInvoke
.Peil de IAsyncResult geretourneerde door
BeginInvoke
om te bepalen wanneer de asynchrone oproep is voltooid en roep vervolgens aanEndInvoke
.Geef een gemachtigde door aan een callback-methode
BeginInvoke
. De methode wordt uitgevoerd op een ThreadPool thread wanneer de asynchrone aanroep is voltooid. De callback-methode roeptEndInvoke
aan.
Belangrijk
Ongeacht welke techniek u gebruikt, roept EndInvoke
u altijd aan om uw asynchrone aanroep te voltooien.
De testmethode en Asynchrone gemachtigde definiƫren
De codevoorbeelden die volgen laten verschillende manieren zien om dezelfde langlopende methode aan te roepen, TestMethod
asynchroon. De TestMethod
methode geeft een consolebericht weer om aan te geven dat het is begonnen met verwerken, een paar seconden slaapt en vervolgens eindigt. TestMethod
heeft een out
parameter om aan te tonen hoe dergelijke parameters worden toegevoegd aan de handtekeningen van BeginInvoke
en EndInvoke
. U kunt parameters op dezelfde manier verwerken ref
.
In het volgende codevoorbeeld ziet u de definitie van TestMethod
en de gemachtigde die AsyncMethodCaller
kan worden gebruikt om asynchroon aan te roepen TestMethod
. Als u de codevoorbeelden wilt compileren, moet u de definities voor TestMethod
en de AsyncMethodCaller
gemachtigde opnemen.
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.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
Wachten op een asynchrone oproep met EndInvoke
De eenvoudigste manier om een methode asynchroon uit te voeren, is door de methode uit te voeren door de methode van BeginInvoke
de gemachtigde aan te roepen, wat werk te doen aan de hoofdthread en vervolgens de methode van EndInvoke
de gemachtigde aan te roepen. EndInvoke
kan de aanroepende thread blokkeren omdat deze pas wordt geretourneerd als de asynchrone aanroep is voltooid. Dit is een goede techniek om te gebruiken met bestands- of netwerkbewerkingen.
Belangrijk
Omdat EndInvoke
dit kan worden geblokkeerd, moet u deze nooit aanroepen vanuit threads die de gebruikersinterface gebruiken.
#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 asynchronous 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 asynchronous 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.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.".
Wachten op een asynchrone oproep met WaitHandle
U kunt een WaitHandle verkrijgen met behulp van de AsyncWaitHandle eigenschap van de IAsyncResult geretourneerde door BeginInvoke
. De WaitHandle melding wordt weergegeven wanneer de asynchrone aanroep is voltooid en u kunt erop wachten door de WaitOne methode aan te roepen.
Als u een WaitHandle, kunt u extra verwerking uitvoeren voor of nadat de asynchrone aanroep is voltooid, maar voordat u aanroept EndInvoke
om de resultaten op te halen.
Notitie
De wachtgreep wordt niet automatisch gesloten wanneer u belt EndInvoke
. Als u alle verwijzingen naar de wachtgreep vrijgeeft, worden systeembronnen vrijgemaakt wanneer garbagecollection de wachtgreep terugvordert. Als u de systeembronnen wilt vrijen zodra u klaar bent met de wachtgreep, moet u deze verwijderen door de methode aan te WaitHandle.Close roepen. Garbagecollection werkt efficiƫnter wanneer wegwerpobjecten expliciet worden verwijderd.
#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 asynchronous 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 asynchronous 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.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 voor voltooiing van Asynchrone aanroep
U kunt de IsCompleted eigenschap van de IAsyncResult geretourneerde door BeginInvoke
gebruiken om te ontdekken wanneer de asynchrone aanroep is voltooid. U kunt dit doen wanneer u de asynchrone aanroep uitvoert vanuit een thread die de gebruikersinterface services. Met polling voor voltooiing kan de aanroepende thread blijven uitvoeren terwijl de asynchrone aanroep wordt uitgevoerd op een 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 asynchronous 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 asynchronous 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.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.".
Een callbackmethode uitvoeren wanneer een asynchrone aanroep is voltooid
Als de thread waarmee de asynchrone aanroep wordt gestart, niet de thread hoeft te zijn die de resultaten verwerkt, kunt u een callback-methode uitvoeren wanneer de aanroep is voltooid. De callback-methode wordt uitgevoerd op een ThreadPool thread.
Als u een callback-methode wilt gebruiken, moet u een AsyncCallback gemachtigde doorgeven BeginInvoke
die de callback-methode vertegenwoordigt. U kunt ook een object doorgeven dat informatie bevat die moet worden gebruikt door de callback-methode. In de callback-methode kunt u de IAsyncResult, wat de enige parameter van de callback-methode is, casten naar een AsyncResult object. Vervolgens kunt u de AsyncResult.AsyncDelegate eigenschap gebruiken om de gemachtigde op te halen die is gebruikt om de oproep te starten, zodat u kunt bellen EndInvoke
.
Opmerkingen in het voorbeeld:
De
threadId
parameter is eenout
parameter ([ByRef
<Out>
in Visual Basic), zodat de invoerwaarde nooit wordt gebruikt doorTestMethod
.TestMethod
Er wordt een dummyvariabele doorgegeven aan deBeginInvoke
aanroep. Als de parameter eenref
parameter (ByRef
in Visual Basic) is, moet de variabele een veld op klasseniveau zijn, zodat deze kan worden doorgegeven aan zowel alsEndInvoke
BeginInvoke
.threadId
De statusinformatie waarnaar wordt doorgegeven
BeginInvoke
, is een notatietekenreeks die door de callback-methode wordt gebruikt om een uitvoerbericht op te maken. Omdat deze als type Objectwordt doorgegeven, moet de statusinformatie worden omgezet in het juiste type voordat deze kan worden gebruikt.De callback wordt uitgevoerd op een ThreadPool thread. ThreadPool threads zijn achtergrondthreads, die de toepassing niet actief houden als de hoofdthread eindigt, dus de hoofdthread van het voorbeeld moet lang genoeg slapen om de callback te voltooien.
#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.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.