Sdílet prostřednictvím


Řízení toku v programech asynchronní (C# a Visual Basic)

Můžete napsat a udržovat asynchronní programy snadněji pomocí Async a Await klíčová slova.Ale výsledky mohou neohlášeného je Pokud nevíte, jak program pracuje.Toto téma sleduje tok řízení prostřednictvím programu jednoduchý asynchronní, chcete-li zobrazit, kdy řízení přejde z jedné metody jiné a jaké informace se přenese pokaždé, když.

[!POZNÁMKA]

Async a Await klíčová slova, které byly zavedeny v aplikaci Visual Studio 2012.Další informace o nových funkcích v této verzi naleznete v tématu Novinky v sadě Visual Studio 2012.

Obecně označit metody, které obsahují asynchronního kódu se Asynchronní (Visual Basic) nebo asynchronní (C#) modifikátor.V metodě, která je označena asynchronní modifikátor, můžete použít Await (Visual Basic) nebo vyčkání (C#) operátor, chcete-li určit, kde se pozastaví metoda čekání na dokončení procesu asynchronní s názvem.Další informace naleznete v tématu Asynchronní asynchronní pro programování a očekávat (C# a Visual Basic).

Následující příklad používá asynchronní metody stáhnout obsah zadaného webu jako řetězec a délku řetězce.Tento příklad obsahuje následující dvě metody.

  • startButton_Click, který vyzývá AccessTheWebAsync a zobrazí výsledek.

  • AccessTheWebAsync, který stáhne obsah webu jako řetězec a vrátí délku řetězce.AccessTheWebAsyncpoužívá asynchronní HttpClient metoda, GetStringAsync(String), chcete-li stáhnout obsah.

Zobrazení, které řádky se zobrazí na strategická místa v celém programu, který vám pomůže pochopit, jak se program spustí a vysvětlit, co se stane, že v každém bodě, který je označen jako číslovány.Zobrazit ukazatele jsou označovány jako "Jedna"až "šest." Popisky představují pořadí, ve kterém program dosáhne tyto řádky kódu.

Následující kód ukazuje přehled programu.

Class MainWindow

    Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) Handles StartButton.Click

        ' ONE
        Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()

        ' FOUR
        Dim contentLength As Integer = Await getLengthTask

        ' SIX
        ResultsTextBox.Text &=
            String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, contentLength)

    End Sub


    Async Function AccessTheWebAsync() As Task(Of Integer)

        ' TWO
        Dim client As HttpClient = New HttpClient() 
        Dim getStringTask As Task(Of String) = 
            client.GetStringAsync("https://msdn.microsoft.com")

        ' THREE
        Dim urlContents As String = Await getStringTask

        ' FIVE
        Return urlContents.Length
    End Function

End Class
public partial class MainWindow : Window
{
    // . . .
    private async void startButton_Click(object sender, RoutedEventArgs e)
    {
        // ONE
        Task<int> getLengthTask = AccessTheWebAsync();

        // FOUR
        int contentLength = await getLengthTask;

        // SIX
        resultsTextBox.Text +=
            String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
    }


    async Task<int> AccessTheWebAsync()
    {
        // TWO
        HttpClient client = new HttpClient();
        Task<string> getStringTask =
            client.GetStringAsync("https://msdn.microsoft.com");

        // THREE                 
        string urlContents = await getStringTask;

        // FIVE
        return urlContents.Length;
    }
}

Každý s popisem umístění "Jedna"až "šest," zobrazí informace o aktuálním stavu programu.Následující výstup je vyráběn.

ONE:   Entering startButton_Click.
           Calling AccessTheWebAsync.

TWO:   Entering AccessTheWebAsync.
           Calling HttpClient.GetStringAsync.

THREE: Back in AccessTheWebAsync.
           Task getStringTask is started.
           About to await getStringTask & return a Task<int> to startButton_Click.

FOUR:  Back in startButton_Click.
           Task getLengthTask is started.
           About to await getLengthTask -- no caller to return to.

FIVE:  Back in AccessTheWebAsync.
           Task getStringTask is complete.
           Processing the return statement.
           Exiting from AccessTheWebAsync.

SIX:   Back in startButton_Click.
           Task getLengthTask is finished.
           Result from AccessTheWebAsync is stored in contentLength.
           About to display contentLength and exit.

Length of the downloaded string: 33946.

Nastavit Program

Kód, který používá toto téma si můžete stáhnout z webu MSDN nebo je možné ji vytvořit sami.

[!POZNÁMKA]

Chcete-li spustit příklad, musí mít 2012 Visual Studio, Visual Studio Express 2012, nebo 4.5 rozhraní .NET Framework nainstalované v počítači.

Hh873191.collapse_all(cs-cz,VS.110).gifStáhnout Program

Můžete stáhnout žádost o tomto tématu z asynchronní vzorku: tok řízení v programech asynchronní.Následující postup otevření a spuštění programu.

  1. Stažený soubor rozbalit a poté spustit Visual Studio 2012.

  2. Na panelu nabídky vyberte možnosti Soubor, Otevřít, Projekt/řešení.

  3. Přejděte do složky obsahující unzipped ukázkový kód, otevřete soubor řešení (.sln) a pak zvolte klávesu F5, sestavte a spusťte projekt.

Hh873191.collapse_all(cs-cz,VS.110).gifProgram sestavit sami

Následující projekt Windows Presentation Foundation (WPF) obsahuje příklad kódu pro toto téma.

Chcete-li spustit projekt, proveďte následující kroky:

  1. Spusťte aplikaci Visual Studio.

  2. V panelu nabídek zvolte Soubor, Nový, Projekt.

    Otevře se dialogové okno Nový projekt.

  3. V Nainstalované šablony podokně zvolte jazyka Visual Basic nebo **Visual C#**a pak zvolte Aplikace WPF ze seznamu typy projektů.

  4. Zadejte AsyncTracer jako název projektu a pak zvolte OK tlačítko.

    V podokně Řešení - průzkumník se zobrazí nový projekt.

  5. V editoru Visual Studio kód, zvolte MainWindow.xaml kartu.

    Pokud na kartě není zobrazen, otevřete místní nabídku pro MainWindow.xaml v Průzkumníkua pak zvolte Zobrazit kód.

  6. V XAML zobrazení MainWindow.xaml, nahraďte kód následujícím kódem.

    <Window
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="MainWindow"
        Title="Control Flow Trace" Height="350" Width="525">
        <Grid>
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="221,10,0,0" VerticalAlignment="Top" Width="75"/>
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="510" Height="265" FontFamily="Lucida Console" FontSize="10" VerticalScrollBarVisibility="Visible" d:LayoutOverrides="HorizontalMargin"/>
    
        </Grid>
    </Window>
    
    <Window
            xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="AsyncTracer.MainWindow"
            Title="Control Flow Trace" Height="350" Width="592">
        <Grid>
            <Button x:Name="startButton" Content="Start&#xa;" HorizontalAlignment="Left" Margin="250,10,0,0" VerticalAlignment="Top" Width="75" Height="24"  Click="startButton_Click" d:LayoutOverrides="GridBox"/>
            <TextBox x:Name="resultsTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="576" Height="265" FontFamily="Lucida Console" FontSize="10" VerticalScrollBarVisibility="Visible" Grid.ColumnSpan="3"/>
        </Grid>
    </Window>
    

    Jednoduché okno, které obsahuje textové pole a tlačítko se zobrazí v Návrh zobrazení MainWindow.xaml.

  7. Přidejte referenci na System.Net.Http.

  8. V Průzkumníku, otevřete místní nabídku pro MainWindow.xaml.vb nebo MainWindow.xaml.cs a pak zvolte Zobrazit kód.

  9. V MainWindow.xaml.vb nebo MainWindow.xaml.cs kód nahraďte následující kód.

    ' Add an Imports statement and a reference for System.Net.Http.
    Imports System.Net.Http
    
    Class MainWindow
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) Handles StartButton.Click
    
            ' The display lines in the example lead you through the control shifts.
            ResultsTextBox.Text &= "ONE:   Entering StartButton_Click." & vbCrLf &
                "           Calling AccessTheWebAsync." & vbCrLf
    
            Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
    
            ResultsTextBox.Text &= vbCrLf & "FOUR:  Back in StartButton_Click." & vbCrLf &
                "           Task getLengthTask is started." & vbCrLf &
                "           About to await getLengthTask -- no caller to return to." & vbCrLf
    
            Dim contentLength As Integer = Await getLengthTask
    
            ResultsTextBox.Text &= vbCrLf & "SIX:   Back in StartButton_Click." & vbCrLf &
                "           Task getLengthTask is finished." & vbCrLf &
                "           Result from AccessTheWebAsync is stored in contentLength." & vbCrLf &
                "           About to display contentLength and exit." & vbCrLf
    
            ResultsTextBox.Text &=
                String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, contentLength)
        End Sub
    
    
        Async Function AccessTheWebAsync() As Task(Of Integer)
    
            ResultsTextBox.Text &= vbCrLf & "TWO:   Entering AccessTheWebAsync."
    
            ' Declare an HttpClient object.
            Dim client As HttpClient = New HttpClient()
    
            ResultsTextBox.Text &= vbCrLf & "           Calling HttpClient.GetStringAsync." & vbCrLf
    
            ' GetStringAsync returns a Task(Of String). 
            Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com")
    
            ResultsTextBox.Text &= vbCrLf & "THREE: Back in AccessTheWebAsync." & vbCrLf &
                "           Task getStringTask is started."
    
            ' AccessTheWebAsync can continue to work until getStringTask is awaited.
    
            ResultsTextBox.Text &=
                vbCrLf & "           About to await getStringTask & return a Task(Of Integer) to StartButton_Click." & vbCrLf
    
            ' Retrieve the website contents when task is complete.
            Dim urlContents As String = Await getStringTask
    
            ResultsTextBox.Text &= vbCrLf & "FIVE:  Back in AccessTheWebAsync." &
                vbCrLf & "           Task getStringTask is complete." &
                vbCrLf & "           Processing the return statement." &
                vbCrLf & "           Exiting from AccessTheWebAsync." & vbCrLf
    
            Return urlContents.Length
        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;
    
    // Add a using directive and a reference for System.Net.Http;
    using System.Net.Http;
    
    namespace AsyncTracer
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private async void startButton_Click(object sender, RoutedEventArgs e)
            {
                // The display lines in the example lead you through the control shifts.
                resultsTextBox.Text += "ONE:   Entering startButton_Click.\r\n" +
                    "           Calling AccessTheWebAsync.\r\n";
    
                Task<int> getLengthTask = AccessTheWebAsync();
    
                resultsTextBox.Text += "\r\nFOUR:  Back in startButton_Click.\r\n" +
                    "           Task getLengthTask is started.\r\n" +
                    "           About to await getLengthTask -- no caller to return to.\r\n";
    
                int contentLength = await getLengthTask;
    
                resultsTextBox.Text += "\r\nSIX:   Back in startButton_Click.\r\n" +
                    "           Task getLengthTask is finished.\r\n" +
                    "           Result from AccessTheWebAsync is stored in contentLength.\r\n" +
                    "           About to display contentLength and exit.\r\n";
    
                resultsTextBox.Text +=
                    String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
            }
    
    
            async Task<int> AccessTheWebAsync()
            {
                resultsTextBox.Text += "\r\nTWO:   Entering AccessTheWebAsync.";
    
                // Declare an HttpClient object.
                HttpClient client = new HttpClient();
    
                resultsTextBox.Text += "\r\n           Calling HttpClient.GetStringAsync.\r\n";
    
                // GetStringAsync returns a Task<string>. 
                Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");
    
                resultsTextBox.Text += "\r\nTHREE: Back in AccessTheWebAsync.\r\n" +
                    "           Task getStringTask is started.";
    
                // AccessTheWebAsync can continue to work until getStringTask is awaited.
    
                resultsTextBox.Text +=
                    "\r\n           About to await getStringTask and return a Task<int> to startButton_Click.\r\n";
    
                // Retrieve the website contents when task is complete.
                string urlContents = await getStringTask;
    
                resultsTextBox.Text += "\r\nFIVE:  Back in AccessTheWebAsync." +
                    "\r\n           Task getStringTask is complete." +
                    "\r\n           Processing the return statement." +
                    "\r\n           Exiting from AccessTheWebAsync.\r\n";
    
                return urlContents.Length;
            }
        }
    }
    
  10. Zvolte klávesu F5, chcete-li spustit program a pak zvolte Start tlačítko.

    By se měl zobrazit následující výstup.

    ONE:   Entering startButton_Click.
               Calling AccessTheWebAsync.
    
    TWO:   Entering AccessTheWebAsync.
               Calling HttpClient.GetStringAsync.
    
    THREE: Back in AccessTheWebAsync.
               Task getStringTask is started.
               About to await getStringTask & return a Task<int> to startButton_Click.
    
    FOUR:  Back in startButton_Click.
               Task getLengthTask is started.
               About to await getLengthTask -- no caller to return to.
    
    FIVE:  Back in AccessTheWebAsync.
               Task getStringTask is complete.
               Processing the return statement.
               Exiting from AccessTheWebAsync.
    
    SIX:   Back in startButton_Click.
               Task getLengthTask is finished.
               Result from AccessTheWebAsync is stored in contentLength.
               About to display contentLength and exit.
    
    Length of the downloaded string: 33946.
    

Trasovací Program

Hh873191.collapse_all(cs-cz,VS.110).gifKroky 1 a 2

Zobrazení prvních dvou řádků sledovat cestu jako startButton_Click volání AccessTheWebAsync, a AccessTheWebAsync vyvolá asynchronní HttpClient metoda GetStringAsync(String).Následující obrázek popisuje volání metody z metody.

Kroky 1 a 2

Návratový typ obou AccessTheWebAsync a client.GetStringAsync je Task<TResult>.Pro AccessTheWebAsync, TResult je celé číslo.Pro GetStringAsync, TResult je řetězec.Další informace o asynchronní metody návratové typy, viz Typy vrácení asynchronní (C# a Visual Basic).

Asynchronní metody vracející úkol vrátí instanci úlohy, při řízení zpět k volajícímu.Ovládací prvek se vrátí z asynchronní metody do jeho volajícího buď při Await nebo await operátor při volané metody nebo po ukončení volané metody.Zobrazení řádků, které jsou označovány jako "Tři"až "ŠESTI" sledovat tuto část procesu.

Hh873191.collapse_all(cs-cz,VS.110).gifKrok 3

V AccessTheWebAsync, asynchronní metody GetStringAsync(String) se nazývá stáhnout obsah cílové webové stránky.Ovládací prvek se vrátí z client.GetStringAsync na AccessTheWebAsync při client.GetStringAsync vrátí.

client.GetStringAsync Metoda vrátí řetězec, který je přiřazen úkol getStringTask proměnné v AccessTheWebAsync.Následující řádek v programu příklad ukazuje volání client.GetStringAsync a přiřazení.

Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com")
Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");

Úkol si lze představit jako promise podle client.GetStringAsync nakonec vyrábět vlastní řetězec.Do té doby Pokud AccessTheWebAsync má práce provést, která nezávisí na přislíbená řetězec z client.GetStringAsync, že můžete pokračovat v práci při client.GetStringAsync čeká.V tomto příkladu představují následující řádky výstupu, které jsou označeny "Tři", příležitost k nezávislé práci

THREE: Back in AccessTheWebAsync.
           Task getStringTask is started.
           About to await getStringTask & return a Task<int> to startButton_Click.

Následující příkaz pozastaví průběh v AccessTheWebAsync při getStringTask imunofluorescenčním.

Dim urlContents As String = Await getStringTask
string urlContents = await getStringTask;

Následující obrázek znázorňuje tok řízení, z client.GetStringAsync k přiřazení k getStringTask a od okamžiku vytvoření getStringTask na žádost provozovatele await.

Krok, tři

Pozastaví výraz await AccessTheWebAsync až client.GetStringAsync vrátí.Do té doby vrací řízení volajícímu AccessTheWebAsync, startButton_Click.

[!POZNÁMKA]

Obvykle můžete očekávat volání asynchronní metody okamžitě.Jeden z následujících přiřazení například nahradit předchozí kód, který vytvoří a potom čeká getStringTask:

  • Visual Basic:Dim urlContents As String = Await client.GetStringAsync("https://msdn.microsoft.com")

  • C#:string urlContents = await client.GetStringAsync("https://msdn.microsoft.com");

V tomto tématu je později použit operátor await pro výstupní řádky, které označí tok řízení prostřednictvím programu.

Hh873191.collapse_all(cs-cz,VS.110).gifKrok 4

Vrátit deklarovaný typ AccessTheWebAsync je Task(Of Integer) v jazyce Visual Basic a Task<int> v jazyce C#.Proto, když AccessTheWebAsync je pozastaveno, vrátí úkolu celé číslo startButton_Click.Je třeba si uvědomit, že vrácené úkolu není getStringTask.Vrácené úkol je nový úkol celé číslo, které představuje, co je ještě třeba provést v metodě zavěšené AccessTheWebAsync.Úkol je promise z AccessTheWebAsync k výrobě celé číslo, pokud je úkol dokončen.

Uvedený příkaz přiřazuje tento úkol getLengthTask proměnné.

Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
Task<int> getLengthTask = AccessTheWebAsync();

Jako v AccessTheWebAsync, startButton_Click můžete pokračovat v práci, která nezávisí na výsledcích asynchronní úlohy (getLengthTask) dokud imunofluorescenčním úkolu.Následující řádky výstupu představují práce.

FOUR:  Back in startButton_Click.
           Task getLengthTask is started.
           About to await getLengthTask -- no caller to return to.

V průběhu startButton_Click se pozastavuje při getLengthTask imunofluorescenčním.Uvedený přiřazovací příkaz pozastaví startButton_Click až AccessTheWebAsync je dokončena.

Dim contentLength As Integer = Await getLengthTask
int contentLength = await getLengthTask;

Na následujícím obrázku šipky ukazují tok řízení z výrazu await v AccessTheWebAsync k přiřazení hodnoty k getLengthTask, následované běžného zpracování v startButton_Click až getLengthTask imunofluorescenčním.

Krok, čtyři

Hh873191.collapse_all(cs-cz,VS.110).gifKrok 5

Při client.GetStringAsync signalizuje, že je dokončeno zpracování v AccessTheWebAsync se uvolní z pozastavení, můžete pokračovat po příkazu await.Následující řádky výstupu představují pokračování zpracování.

FIVE:  Back in AccessTheWebAsync.
           Task getStringTask is complete.
           Processing the return statement.
           Exiting from AccessTheWebAsync.

Operand příkaz return urlContents.Length, je uložen v úloze, AccessTheWebAsync vrátí.Výraz await získá tuto hodnotu z getLengthTask v startButton_Click.

Následující obrázek znázorňuje přenos řízení po client.GetStringAsync (a getStringTask) byly dokončeny.

Krok, PĚT

AccessTheWebAsyncSpustí dokončení a ovládací prvek se vrátí do startButton_Click, která čeká na dokončení.

Hh873191.collapse_all(cs-cz,VS.110).gifKrok 6

Při AccessTheWebAsync signály, které je dokončeno zpracování můžete pokračovat po příkazu await v startButton_Async.Program má ve skutečnosti žádnou další akci nelze provést.

Následující řádky výstupu představují pokračování zpracování v startButton_Async:

SIX:   Back in startButton_Click.
           Task getLengthTask is finished.
           Result from AccessTheWebAsync is stored in contentLength.
           About to display contentLength and exit.

Výraz await získá z getLengthTask celočíselnou hodnotu, která je operand příkaz return v AccessTheWebAsync.Uvedený příkaz přiřazuje tuto hodnotu contentLength proměnné.

Dim contentLength As Integer = Await getLengthTask
int contentLength = await getLengthTask;

Následující obrázek znázorňuje návrat ovládacího prvku z AccessTheWebAsync na startButton_Click.

Krok, šest

Viz také

Úkoly

Názorný postup: Přístup K webu pomocí asynchronní a vyčkání (C# a Visual Basic)

Postupy: Použití ladicího programu u asynchronních metod

Koncepty

Asynchronní asynchronní pro programování a očekávat (C# a Visual Basic)

Typy vrácení asynchronní (C# a Visual Basic)

Další zdroje

Asynchronní: Řízení průtoku v programech asynchronní (C# a Visual Basic)