Asynchrone Rückgabetypen (C# und Visual Basic)
Asynchrone Methoden verfügen über drei mögliche Rückgabetypen: Task<TResult>, Task und void.In Visual Basic wird der ungültige Rückgabetyp als Sub Prozedur geschrieben.Weitere Informationen über asynchrone Methoden, finden Sie unter Asynchrone Programmierung mit Async und Await (C# und Visual Basic).
Jeder Rückgabetyp wird in einem der folgenden Abschnitte überprüft, und Sie können ein vollständiges Beispiel suchen, das alle drei Typen am Ende des Themas verwendet.
Hinweis |
---|
Um das Beispiel auszuführen, müssen Sie Visual Studio 2012, Visual Studio Express 2012 für Windows Desktop oder .NET Framework 4.5 enthalten, das auf dem Computer installiert ist. |
Dieses Thema enthält folgende Abschnitte.
- Aufgabe (T) Rückgabetyp
- Weisen Sie Rückgabetyp eine Arbeit zu
- Ungültiger Rückgabetyp
- Vollständiges Beispiel
- Verwandte Themen
Aufgabe (T) Rückgabetyp
Der Task<TResult> Rückgabetyp wird für eine asynchrone Methode verwendet, die eine - Anweisung Return (Visual Basic) oder Rückgabe (C#) enthält, in der der Operand Typ TResult verfügt.
Im folgenden Beispiel enthält die asynchrone Methode TaskOfT_MethodAsync eine return-Anweisung, die eine ganze Zahl zurückgibt.Daher muss die Methodendeklaration einen Rückgabetyp Task(Of Integer) in Visual Basic oder Task<int> in C# angeben.
' TASK(OF T) EXAMPLE
Async Function TaskOfT_MethodAsync() As Task(Of Integer)
' The body of an async method is expected to contain an awaited
' asynchronous call.
' Task.FromResult is a placeholder for actual work that returns a string.
Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString())
' The method then can process the result in some way.
Dim leisureHours As Integer
If today.First() = "S" Then
leisureHours = 16
Else
leisureHours = 5
End If
' Because the return statement specifies an operand of type Integer, the
' method must have a return type of Task(Of Integer).
Return leisureHours
End Function
// TASK<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
// The body of the method is expected to contain an awaited asynchronous
// call.
// Task.FromResult is a placeholder for actual work that returns a string.
var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
// The method then can process the result in some way.
int leisureHours;
if (today.First() == 'S')
leisureHours = 16;
else
leisureHours = 5;
// Because the return statement specifies an operand of type int, the
// method must have a return type of Task<int>.
return leisureHours;
}
Wenn TaskOfT_MethodAsync aus einem Erwartungsausdruck aufgerufen wird, ruft der Erwartungsausdruck den ganzzahligen Wert ab (den Wert von leisureHours) der in der Aufgabe gespeichert wird, die von TaskOfT_MethodAsync zurückgegeben wird.Weitere Informationen zu erwarten Sie Ausdrücke, finden Sie unter Await-Operator (Visual Basic) oder await (C#-Referenz).
Der folgende Code ruft auf und erwartet Methode TaskOfT_MethodAsync.Das Ergebnis wird zur result1-Variablen zugewiesen.
' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
// Call and await the Task<T>-returning async method in the same statement.
int result1 = await TaskOfT_MethodAsync();
Sie können, wie dies geschieht, indem es den Aufruf TaskOfT_MethodAsync mit Await oder von await trennt, wie im folgenden Code veranschaulicht besser verstehen.Ein Aufruf der - Methode TaskOfT_MethodAsync, die nicht sofort erwartete gibt ein Task(Of Integer) oder Task<int> ist, wie Sie aus der Deklaration der Methode Erwartungen.Die Aufgabe wird zur integerTask-Variable im Beispiel zugewiesen.Da integerTaskTask<TResult> handelt, enthält sie eine Result-Eigenschaft des Typs TResult.In diesem Fall stellt TResult einen ganzzahligen Typ dar.Wenn Await oder await zu integerTask angewendet wird, wertet der Erwartungsausdruck zum Inhalt der Result-Eigenschaft von integerTask aus.Der Wert wird der result2-Variablen zugewiesen.
Vorsicht |
---|
Die Result-Eigenschaft ist eine blockierende Eigenschaft.Wenn Sie versuchen, auf sie zuzugreifen, bevor seine Aufgabe beendet ist, wird der Thread, der derzeit aktiv ist blockiert, bis die Aufgabe abgeschlossen und der Wert verfügbar ist.In den meisten Fällen sollten Sie auf den Wert zugreifen, indem Sie Await oder await verwenden, anstatt auf die - Eigenschaft, direkt zuzugreifen. |
' Call and await in separate statements.
Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync()
' You can do other work that does not rely on resultTask before awaiting.
textBox1.Text &= String.Format("Application can continue working while the Task(Of T) runs. . . . " & vbCrLf)
Dim result2 As Integer = Await integerTask
// Call and await in separate statements.
Task<int> integerTask = TaskOfT_MethodAsync();
// You can do other work that does not rely on integerTask before awaiting.
textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");
int result2 = await integerTask;
Die Anzeigeanweisungen im folgenden Code überprüfen, ob die Werte der result1-Variable, der result2-Variablen und der - Eigenschaft Result identisch sind.Beachten Sie, dass auf die Result-Eigenschaft eine blockierende Eigenschaft ist und nicht zugegriffen werden soll, bevor seine Aufgabe erwartet wurde.
' Display the values of the result1 variable, the result2 variable, and
' the resultTask.Result property.
textBox1.Text &= String.Format(vbCrLf & "Value of result1 variable: {0}" & vbCrLf, result1)
textBox1.Text &= String.Format("Value of result2 variable: {0}" & vbCrLf, result2)
textBox1.Text &= String.Format("Value of resultTask.Result: {0}" & vbCrLf, integerTask.Result)
// Display the values of the result1 variable, the result2 variable, and
// the integerTask.Result property.
textBox1.Text += String.Format("\r\nValue of result1 variable: {0}\r\n", result1);
textBox1.Text += String.Format("Value of result2 variable: {0}\r\n", result2);
textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);
Weisen Sie Rückgabetyp eine Arbeit zu
Asynchrone Methoden, die keine - Anweisung enthalten, oder die eine return-Anweisung enthalten, die keinen Operanden zurückgibt, haben normalerweise einen Rückgabetyp Task.Diese Methoden werden Methoden void-zurückgeben (Sub Prozeduren in Visual Basic) wenn sie geschrieben wurden, um synchron ausgeführt werden.Wenn Sie einen Task Rückgabetyp für eine asynchrone Methode verwenden, kann ein Aufruf von Methoden einen Erwartungsoperator verwenden, um den Abschluss des Aufrufers angehalten, bis die aufgerufene asynchrone Methode beendet wurde.
Im folgenden Beispiel enthält asynchrone Methode Task_MethodAsync keine return-Anweisung.Daher geben Sie einen Rückgabetyp Task für die Methode an, die erwartet werden Task_MethodAsync aktiviert.Die Definition des Typs Task umfasst keine Result-Eigenschaft, um einen Rückgabewert zu speichern.
' TASK EXAMPLE
Async Function Task_MethodAsync() As Task
' The body of an async method is expected to contain an awaited
' asynchronous call.
' Task.Delay is a placeholder for actual work.
Await Task.Delay(2000)
textBox1.Text &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)
' This method has no return statement, so its return type is Task.
End Function
// TASK EXAMPLE
async Task Task_MethodAsync()
{
// The body of an async method is expected to contain an awaited
// asynchronous call.
// Task.Delay is a placeholder for actual work.
await Task.Delay(2000);
// Task.Delay delays the following line by two seconds.
textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");
// This method has no return statement, so its return type is Task.
}
Task_MethodAsync wird aufgerufen und erwartet, indem eine Erwartungsanweisung anstelle eines Erwartungsausdrucks verwendet, der an die aufrufende Anweisung für synchrones Sub ähnelt oder Methode void-zurückgibt.Die Anwendung eines Erwartungsoperators in diesem Fall keinen Wert.
Der folgende Code ruft auf und erwartet Methode Task_MethodAsync.
' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
// Call and await the Task-returning async method in the same statement.
await Task_MethodAsync();
Wie im vorherigen Beispiel Task<TResult>, können Sie den Aufruf von Task_MethodAsync aus der Anwendung eines Erwartungsoperators, wie im folgenden Code veranschaulicht trennen.Beachten Sie jedoch, dass Task keine Result-Eigenschaft verfügt und dass kein Wert generiert wird, wenn ein Erwartungsoperator zu Task angewendet wird.
Der folgende Code trennt das Aufrufen von Task_MethodAsync vom Rechnen der Aufgabe, die Task_MethodAsync zurückgibt.
' Call and await in separate statements.
Dim simpleTask As Task = Task_MethodAsync()
' You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text &= String.Format(vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf)
Await simpleTask
// Call and await in separate statements.
Task simpleTask = Task_MethodAsync();
// You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");
await simpleTask;
Ungültiger Rückgabetyp
Der Hauptverwendungszweck des ungültigen Rückgabetyp (Sub Prozeduren in Visual Basic) ist in Ereignishandlern, in denen ein Ungültiger Rückgabetyp erforderlich ist.Eine void-Rückgabe kann auch verwendet werden, um das void-Zurückgeben von Methoden oder für Methoden zu überschreiben, die Aktivitäten ausführen, die kategorisiert werden können, wie "Feuer - und - vergessen Sie". Sie sollten nach Möglichkeit Task zurückgeben, da eine void-zurückkehrende asynchrone Methode nicht erwartet werden kann.Jeder Aufrufer einer solchen Methode muss in der Lage sein, abgeschlossen fortzusetzen, ohne auf die aufgerufene asynchrone Methode zu warten, bis zu beenden, und der Aufrufer muss unabhängig aller Werte oder Ausnahmen sein, die die asynchrone Methode generiert.
Der Aufrufer void-zurückkehrenden einer asynchronen Methode kann Ausnahmen auffangen, die von der - Methode ausgelöst werden, und solche nicht behandelten Ausnahmen sind wahrscheinlich, die Anwendung zu und bewirkt.Wenn eine Ausnahme in einer asynchronen Methode auftritt, die Task oder Task<TResult> zurückgibt, wird die Ausnahme in der zurückgegebenen Aufgabe gespeichert und erneut ausgelöst, wenn die Aufgabe erwartet wird.Deshalb müssen Sie sicherstellen, dass jede asynchrone Methode, die eine Ausnahme erzeugen können, einen Rückgabetyp Task oder Task<TResult> verfügt und die Aufrufe der - Methode erwartet werden.
Weitere Informationen darüber, wie Ausnahmen in asynchronen Methoden, finden Sie unter try-catch (C#-Referenz) oder Try...Catch...Finally-Anweisung (Visual Basic) abfängt.
Der folgende Code definiert einen asynchronen Ereignishandler.
' SUB EXAMPLE
Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click
textBox1.Clear()
' Start the process and await its completion. DriverAsync is a
' Task-returning async method.
Await DriverAsync()
' Say goodbye.
textBox1.Text &= vbCrLf & "All done, exiting button-click event handler."
End Sub
// VOID EXAMPLE
private async void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Clear();
// Start the process and await its completion. DriverAsync is a
// Task-returning async method.
await DriverAsync();
// Say goodbye.
textBox1.Text += "\r\nAll done, exiting button-click event handler.";
}
Vollständiges Beispiel
Im folgenden Projekt (Windows Presentation Foundation) enthält die Codebeispiele in diesem Thema.
Um das Projekt auszuführen, müssen Sie die folgenden Schritte aus:
Starten Sie Visual Studio.
Wählen Sie in der Menüleiste Datei, Neu, Projekt aus.
Das Dialogfeld Neues Projekt wird angezeigt.
In Installiert wählen Kategorie Vorlagen, Visual Basic oder Visual C# aus und wählen dann Fenster aus.Wählen Sie WPF-Anwendung aus der Liste der - Projekttypen aus.
Geben Sie AsyncReturnTypes als Namen für das Projekt ein, und wählen Sie dann die Schaltfläche OK aus.
Das neue Projekt wird im Projektmappen-Explorer angezeigt.
In Visual Studio MainWindow.xaml wählen Sie die Registerkarte aus.
Wenn die Registerkarte nicht sichtbar ist, öffnen Sie das Kontextmenü für MainWindow.xaml in Projektmappen-Explorer, und wählen Sie dann Öffnen aus.
XAML im Fenster der Datei MainWindow.xaml, ersetzen Sie den Code durch den folgenden Code.
<Window x:Class="MainWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button x:Name="button1" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="button1_Click"/> <TextBox x:Name="textBox1" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/> </Grid> </Window>
<Window x:Class="AsyncReturnTypes.MainWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button x:Name="button1" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="button1_Click"/> <TextBox x:Name="textBox1" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/> </Grid> </Window>
Ein einfaches Fenster, das ein Textfeld und eine Schaltfläche enthält, wird im Fenster Entwurf der Datei MainWindow.xaml.
In Projektmappen-Explorer öffnen Sie das Kontextmenü für MainWindow.xaml.cs oder MainWindow.xaml.vb, und wählen Sie dann Code anzeigen aus.
Ersetzen Sie den Code in "MainWindow.xaml.vb" oder durch den folgenden Code.
Class MainWindow ' SUB EXAMPLE Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click textBox1.Clear() ' Start the process and await its completion. DriverAsync is a ' Task-returning async method. Await DriverAsync() ' Say goodbye. textBox1.Text &= vbCrLf & "All done, exiting button-click event handler." End Sub Async Function DriverAsync() As Task ' Task(Of T) ' Call and await the Task(Of T)-returning async method in the same statement. Dim result1 As Integer = Await TaskOfT_MethodAsync() ' Call and await in separate statements. Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync() ' You can do other work that does not rely on resultTask before awaiting. textBox1.Text &= String.Format("Application can continue working while the Task(Of T) runs. . . . " & vbCrLf) Dim result2 As Integer = Await integerTask ' Display the values of the result1 variable, the result2 variable, and ' the resultTask.Result property. textBox1.Text &= String.Format(vbCrLf & "Value of result1 variable: {0}" & vbCrLf, result1) textBox1.Text &= String.Format("Value of result2 variable: {0}" & vbCrLf, result2) textBox1.Text &= String.Format("Value of resultTask.Result: {0}" & vbCrLf, integerTask.Result) ' Task ' Call and await the Task-returning async method in the same statement. Await Task_MethodAsync() ' Call and await in separate statements. Dim simpleTask As Task = Task_MethodAsync() ' You can do other work that does not rely on simpleTask before awaiting. textBox1.Text &= String.Format(vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf) Await simpleTask End Function ' TASK(OF T) EXAMPLE Async Function TaskOfT_MethodAsync() As Task(Of Integer) ' The body of an async method is expected to contain an awaited ' asynchronous call. ' Task.FromResult is a placeholder for actual work that returns a string. Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString()) ' The method then can process the result in some way. Dim leisureHours As Integer If today.First() = "S" Then leisureHours = 16 Else leisureHours = 5 End If ' Because the return statement specifies an operand of type Integer, the ' method must have a return type of Task(Of Integer). Return leisureHours End Function ' TASK EXAMPLE Async Function Task_MethodAsync() As Task ' The body of an async method is expected to contain an awaited ' asynchronous call. ' Task.Delay is a placeholder for actual work. Await Task.Delay(2000) textBox1.Text &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf) ' This method has no return statement, so its return type is Task. End Function End Class
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace AsyncReturnTypes { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } // VOID EXAMPLE private async void button1_Click(object sender, RoutedEventArgs e) { textBox1.Clear(); // Start the process and await its completion. DriverAsync is a // Task-returning async method. await DriverAsync(); // Say goodbye. textBox1.Text += "\r\nAll done, exiting button-click event handler."; } async Task DriverAsync() { // Task<T> // Call and await the Task<T>-returning async method in the same statement. int result1 = await TaskOfT_MethodAsync(); // Call and await in separate statements. Task<int> integerTask = TaskOfT_MethodAsync(); // You can do other work that does not rely on integerTask before awaiting. textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n"); int result2 = await integerTask; // Display the values of the result1 variable, the result2 variable, and // the integerTask.Result property. textBox1.Text += String.Format("\r\nValue of result1 variable: {0}\r\n", result1); textBox1.Text += String.Format("Value of result2 variable: {0}\r\n", result2); textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result); // Task // Call and await the Task-returning async method in the same statement. await Task_MethodAsync(); // Call and await in separate statements. Task simpleTask = Task_MethodAsync(); // You can do other work that does not rely on simpleTask before awaiting. textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n"); await simpleTask; } // TASK<T> EXAMPLE async Task<int> TaskOfT_MethodAsync() { // The body of the method is expected to contain an awaited asynchronous // call. // Task.FromResult is a placeholder for actual work that returns a string. var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString()); // The method then can process the result in some way. int leisureHours; if (today.First() == 'S') leisureHours = 16; else leisureHours = 5; // Because the return statement specifies an operand of type int, the // method must have a return type of Task<int>. return leisureHours; } // TASK EXAMPLE async Task Task_MethodAsync() { // The body of an async method is expected to contain an awaited // asynchronous call. // Task.Delay is a placeholder for actual work. await Task.Delay(2000); // Task.Delay delays the following line by two seconds. textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n"); // This method has no return statement, so its return type is Task. } } }
Wählen Sie die F5-TASTE, um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start aus.
Die folgende Ausgabe sollte angezeigt werden.
Application can continue working while the Task<T> runs. . . . Value of result1 variable: 5 Value of result2 variable: 5 Value of integerTask.Result: 5 Sorry for the delay. . . . Application can continue working while the Task runs. . . . Sorry for the delay. . . . All done, exiting button-click event handler.
Siehe auch
Aufgaben
Exemplarische Vorgehensweise: Zugreifen auf das Web mit Async und Await (C# und Visual Basic)
Exemplarische Vorgehensweise: Verwenden des Debuggers mit Async-Methoden
Referenz
Konzepte
Ablaufsteuerung in asynchronen Programmen (C# und Visual Basic)