Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
.NET Framework ermöglicht es, jede Methode auch asynchron aufzurufen. Definieren Sie einen Delegaten mit der gleichen Signatur wie die Methode, die Sie aufrufen möchten. Die Common Language Runtime definiert für diesen Delegaten automatisch eine BeginInvoke-Methode und eine EndInvoke-Methode mit den entsprechenden Signaturen.
Die BeginInvoke-Methode wird zum Starten des asynchronen Aufrufs verwendet. Sie weist dieselben Parameter auf wie die asynchron auszuführende Methode sowie zwei zusätzliche Parameter, die weiter unten beschrieben werden. BeginInvoke wird sofort beendet, ohne auf den Abschluss des asynchronen Aufrufs zu warten. BeginInvoke gibt ein IasyncResult zurück, das zur Überwachung des Aufrufstatus verwendet werden kann.
Die EndInvoke-Methode wird zum Abrufen der Ergebnisse des asynchronen Aufrufs verwendet. Sie kann jederzeit nach BeginInvoke aufgerufen werden. Wenn der asynchrone Aufruf noch nicht vollständig ausgeführt wurde, blockiert EndInvoke bis zum Abschluss dieses Aufrufs. Zu den Parametern von EndInvoke gehören der out-Parameter und der ref-Parameter (<Out>-ByRef und ByRef in Visual Basic) der Methode, die asynchron ausgeführt werden soll, sowie das IAsyncResult, das von BeginInvoke zurückgegeben wird.
Hinweis Das IntelliSense-Feature in Visual Studio .NET zeigt die Parameter von BeginInvoke und EndInvoke an. Wenn Sie nicht Visual Studio oder ein ähnliches Tool verwenden oder wenn Sie C# mit Visual Studio .NET verwenden, finden Sie unter Asynchrone Methodensignaturen eine Beschreibung der Parameter, die die Common Language Runtime für diese Methoden definiert.
Der Code in diesem Abschnitt veranschaulicht die vier gebräuchlichen Arten der Verwendung von BeginInvoke und EndInvoke bei asynchronen Aufrufen. Nach dem Aufruf von BeginInvoke können Sie folgende Aktionen ausführen:
Sie können etwas Arbeit erledigen und dann EndInvoke aufrufen, um eine Blockierung bis zum Abschluss des Aufrufs zu erreichen.
Sie können ein WaitHandle mit Hilfe von IAsyncResult.AsyncWaitHandle abrufen, dessen WaitOne-Methode zum Blockieren der Ausführung verwenden, bis WaitHandle signalisiert wird, und dann EndInvoke aufrufen.
Sie können das von BeginInvoke zurückgegebene IAsyncResult abrufen, um zu bestimmen, wann der asynchrone Aufruf beendet wurde, und dann EndInvoke aufrufen.
Sie können einen Delegaten für eine Rückrufmethode an BeginInvoke übergeben. Die Methode wird auf einem ThreadPool-Thread ausgeführt, wenn der asynchrone Aufruf abgeschlossen wird, und kann EndInvoke aufrufen.
Vorsicht Rufen Sie nach Abschluss des asynchronen Aufrufs immer EndInvoke auf.
Testmethode und asynchroner Delegat
In allen vier Beispielen wird dieselbe langlebige Testmethode TestMethod verwendet. Diese Methode zeigt in einer Konsolenmeldung an, dass die Verarbeitung begonnen hat, ist dann für einige Sekunden im Ruhezustand und wird anschließend beendet. TestMethod weist einen out-Parameter auf (<Out>-ByRef in Visual Basic), um zu veranschaulichen, wie solche Parameter den Signaturen von BeginInvoke und EndInvoke hinzugefügt werden. ref-Parameter (ByRef in Visual Basic) können ähnlich behandelt werden.
Das folgende Codebeispiel veranschaulicht TestMethod und den Delegaten, der diese darstellt. Wenn Sie eines dieser Beispiele verwenden möchten, fügen Sie den Beispielcode an diesen Code an.
Hinweis Zur Vereinfachung der Beispiele wird TestMethod in einer anderen Klasse als
Main()deklariert. Alternativ kann TestMethod eine static-Methode (Shared in Visual Basic) in derselben Klasse sein, dieMain()enthält.
Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
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 = AppDomain.GetCurrentThreadId()
return "MyCallTime was " + callDuration.ToString()
End Function
End Class
' The delegate must have the same signature as the method
' you want to call asynchronously.
Public Delegate Function AsyncDelegate(ByVal callDuration As Integer, _
<Out> ByRef threadId As Integer) As String
[C#]
using System;
using System.Threading;
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 = AppDomain.GetCurrentThreadId();
return "MyCallTime was " + callDuration.ToString();
}
}
// The delegate must have the same signature as the method
// you want to call asynchronously.
public delegate string AsyncDelegate(int callDuration, out int threadId);
Warten auf einen asynchronen Aufruf mit "EndInvoke"
Die einfachste Art der asynchronen Ausführung einer Methode ist das Starten mit BeginInvoke, das Erledigen von Arbeit am Hauptthread und das anschließende Aufrufen von EndInvoke. EndInvoke wird erst bei Abschluss des asynchronen Aufrufs beendet. Dies ist ein gutes Verfahren zur Verwendung bei Datei- oder Netzwerkoperationen, da es jedoch bei EndInvoke blockiert, sollte es nicht aus Threads für die Benutzeroberfläche verwendet werden.
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 dlgt As New AsyncDelegate(AddressOf ad.TestMethod)
' Initiate the asynchronous call.
Dim ar As IAsyncResult = dlgt.BeginInvoke(3000, _
threadId, Nothing, Nothing)
Thread.Sleep(0)
Console.WriteLine("Main thread {0} does some work.", _
AppDomain.GetCurrentThreadId())
' Call EndInvoke to Wait for the asynchronous call to complete,
' and to retrieve the results.
Dim ret As String = dlgt.EndInvoke(threadId, ar)
Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret)
End Sub
End Class
[C#]
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
AppDomain.GetCurrentThreadId());
// Call EndInvoke to Wait for the asynchronous call to complete,
// and to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}
Warten auf einen asynchronen Aufruf mit "WaitHandle"
Das Warten mit einem WaitHandle ist ein gebräuchliches Verfahren für die Threadsynchronisierung. Sie können ein WaitHandle mit der AsyncWaitHandle-Eigenschaft des von BeginInvoke zurückgegebenen IAsyncResult abrufen. WaitHandle wird beim Abschluss des asynchronen Aufrufs signalisiert, und durch Aufrufen von WaitOne kann darauf gewartet werden.
Bei Verwendung eines WaitHandle kann nach Abschluss des asynchronen Aufrufs eine weitere Verarbeitung durchgeführt werden, bevor Sie die Ergebnisse durch Aufrufen von EndInvoke abrufen.
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 dlgt As New AsyncDelegate(AddressOf ad.TestMethod)
' Initiate the asynchronous call.
Dim ar As IAsyncResult = dlgt.BeginInvoke(3000,
threadId, Nothing, Nothing)
Thread.Sleep(0)
Console.WriteLine("Main thread {0} does some work.",
AppDomain.GetCurrentThreadId())
' Wait for the WaitHandle to become signaled.
ar.AsyncWaitHandle.WaitOne()
' Perform additional processing here.
' Call EndInvoke to retrieve the results.
Dim ret As String = dlgt.EndInvoke(threadId, ar)
Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret)
End Sub
End Class
[C#]
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
AppDomain.GetCurrentThreadId());
// Wait for the WaitHandle to become signaled.
ar.AsyncWaitHandle.WaitOne();
// Perform additional processing here.
// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}
Abrufen der asynchronen Aufrufbeendigung
Mit der IsCompleted-Eigenschaft des von BeginInvoke zurückgegebenen IAsyncResult können Sie feststellen, wann der asynchrone Aufruf abgeschlossen wird. Dieses Verfahren ist empfehlenswert, wenn der asynchrone Aufruf aus einem Thread für die Benutzeroberfläche erfolgt. Durch das Abrufen der Beendigung können vom Benutzeroberflächenthread weitere Benutzereingaben verarbeitet werden.
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 dlgt As New AsyncDelegate(AddressOf ad.TestMethod)
' Initiate the asynchronous call.
Dim ar As IAsyncResult = dlgt.BeginInvoke(3000,
threadId, Nothing, Nothing)
' Poll while simulating work.
While ar.IsCompleted = False
Thread.Sleep(10)
End While
' Call EndInvoke to retrieve the results.
Dim ret As String = dlgt.EndInvoke(threadId, ar)
Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret)
End Sub
End Class
[C#]
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);
// Poll while simulating work.
while(ar.IsCompleted == false) {
Thread.Sleep(10);
}
// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}
Ausführen einer Rückrufmethode bei Beendigung eines asynchronen Aufrufs
Wenn der Thread, der den asynchronen Aufruf gestartet hat, die Ergebnisse nicht verarbeiten muss, können Sie bei Beendigung des Aufrufs eine Rückrufmethode ausführen. Die Rückrufmethode wird auf einem ThreadPool-Thread ausgeführt.
Um eine Rückrufmethode verwenden zu können, müssen Sie BeginInvoke an einen AsyncCallback-Delegaten übergeben, der die Methode darstellt. Sie können auch ein Objekt übergeben, das die von der Rückrufmethode zu verwendenden Informationen enthält. Sie können z. B. den Delegaten übergeben, der zum Starten des Aufrufs verwendet wurde, so dass die Rückrufmethode EndInvoke aufrufen kann.
Public Class AsyncMain
' The asynchronous method puts the thread id here.
Private Shared threadId As Integer
Shared Sub Main()
' Create an instance of the test class.
Dim ad As New AsyncDemo()
' Create the delegate.
Dim dlgt As New AsyncDelegate(AddressOf ad.TestMethod)
' Initiate the asynchronous call.
Dim ar As IAsyncResult = dlgt.BeginInvoke(3000, _
threadId, _
AddressOf CallbackMethod, _
dlgt)
Console.WriteLine("Press Enter to close application.")
Console.ReadLine()
End Sub
' Callback method must have the same signature as the
' AsyncCallback delegate.
Shared Sub CallbackMethod(ByVal ar As IAsyncResult)
' Retrieve the delegate.
Dim dlgt As AsyncDelegate = CType(ar.AsyncState, AsyncDelegate)
' Call EndInvoke to retrieve the results.
Dim ret As String = dlgt.EndInvoke(threadId, ar)
Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", threadId, ret)
End Sub
End Class
[C#]
public class AsyncMain {
// Asynchronous method puts the thread id here.
private static int threadId;
static void Main(string[] args) {
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call. Include an AsyncCallback
// delegate representing the callback method, and the data
// needed to call EndInvoke.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId,
new AsyncCallback(CallbackMethod),
dlgt );
Console.WriteLine("Press Enter to close application.");
Console.ReadLine();
}
// Callback method must have the same signature as the
// AsyncCallback delegate.
static void CallbackMethod(IAsyncResult ar) {
// Retrieve the delegate.
AsyncDelegate dlgt = (AsyncDelegate) ar.AsyncState;
// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}