Sdílet prostřednictvím


Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic)

Asynchronní programy lze psát snadněji a intuitivně pomocí funkcí, které jsou zavedeny v Visual Studio 2012.Můžete napsat asynchronního kódu, který vypadá jako synchronní kód a nechat kompilátor zpracování obtížné zpětného volání funkce a pokračování, které obvykle zahrnuje asynchronní kódu.

Další informace o funkci asynchronní, viz Asynchronní programování pomocí modifikátoru Async a operátoru Await (C# a Visual Basic).

Tento návod začíná synchronní aplikace Windows Presentation Foundation (WPF), který sečte počet bajtů v seznamu webů.Návodu převede aplikace asynchronní řešení pomocí nové funkce.

Pokud nechcete, aby aplikace vytvořit sami, můžete stáhnout "asynchronní vzorku: přístup k webové návod (C# a Visual Basic)" z Developer ukázky kódu.

V tomto návodu můžete provést následující úkoly:

  • Create a WPF application.

  • Design a simple WPF MainWindow window.

  • Add a reference.

  • Add Imports statements or using directives.

  • Create a synchronous solution.

  • Test the synchronous solution.

  • Convert GetURLContents to an asynchronous method.

  • Convert SumPageSizes to an asynchronous method.

  • Convert startButton_Click to an asynchronous method.

  • Test the asynchronous solution.

  • Replace GetURLContentsAsync with a .NET Framework method.

  • Complete Code Examples from the Walkthrough

Požadavky

Visual Studio 2012musí být nainstalována v počítači.Další informace naleznete webovém serveru společnosti Microsoft.

Vytvoření aplikace WPF

  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. V jméno text zadejte AsyncExampleWPFa pak zvolte OK tlačítko.

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

Chcete-li navrhnout jednoduché MainWindow WPF

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

  2. Pokud nástrojů okno není zobrazen, otevřete zobrazení nabídky a pak zvolte nástrojů.

  3. Přidat tlačítko řízení a textové pole ovládacího prvku MainWindow okna.

  4. Zvýraznění textové pole ovládací prvek a v Vlastnosti okno, nastavte následující hodnoty:

    • Nastavit jméno vlastnost resultsTextBox.

    • Nastavit Výška vlastnost 250.

    • Nastavit Šířka vlastnost na hodnotu 500.

    • Na textu karta, určení písma s pevnou šířkou, například Lucida Console nebo globální psaný neproporcionálním písmem.

  5. Zvýraznění tlačítko ovládací prvek a v Vlastnosti okno, nastavte následující hodnoty:

    • Nastavit jméno vlastnost startButton.

    • Změňte hodnotu obsahu vlastnost z tlačítko na Start.

  6. Umístěte textové pole a tlačítko tak, aby současně MainWindow okna.

    Další informace o jazyce XAML návrháře WPF, viz Creating a UI by using XAML Designer.

Chcete-li přidat odkaz

  1. V Průzkumníku, zvýrazněte název vašeho projektu.

  2. V řádku nabídek zvolte projektu, Přidat odkaz na.

    Reference Manager zobrazí se dialogové okno.

  3. V horní části dialogového okna ověřte, že projekt je zaměření rozhraní .NET Framework 4.5.

  4. V sestavení oblasti, zvolte Framework Pokud není již vybrána.

  5. Vyberte v seznamu názvů, System.Net.Http políčko.

  6. Zvolte OK tlačítko zavřete dialogové okno.

Chcete-li přidat potřebné příkazy dovozu nebo použití směrnic

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

  2. Přidejte následující Imports příkazy (Visual Basic) nebo using směrnic (C#) v horní části souboru kódu, pokud nejsou správné již přítomen.

    Imports System.Net.Http
    Imports System.Net
    Imports System.IO
    
    using System.Net.Http;
    using System.Net;
    using System.IO;
    

Chcete-li vytvořit synchronní aplikace

  1. V okně návrhu, MainWindow.xaml, poklepejte na položku Start tlačítko, chcete-li vytvořit startButton_Click obslužné rutiny události MainWindow.xaml.vb nebo MainWindow.xaml.cs.Jako alternativu, zvýrazněte Start tlačítko, zvolte obslužné rutiny událostí pro vybrané elementy ikonu v Vlastnosti okna a potom zadejte startButton_Click v klepněte na tlačítko textové pole.

  2. Zkopírujte následující kód do těla ve MainWindow.xaml.vb nebo MainWindow.xaml.cs startButton_Click.

    resultsTextBox.Clear()
    SumPageSizes()
    resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
    
    resultsTextBox.Clear();
    SumPageSizes();
    resultsTextBox.Text += "\r\nControl returned to startButton_Click.";
    

    Kód volá metodu, která jednotky aplikace, SumPageSizesa zobrazí zprávu, když ovládací prvek se vrátí do startButton_Click.

  3. Kód pro synchronní řešení obsahuje následující čtyři metody:

    • SumPageSizes, který získá seznam adres URL webové stránky z SetUpURLList a pak zavolá GetURLContents a DisplayResults zpracovat všechny adresy URL.

    • SetUpURLList, která vytvoří a vrátí seznam webových adres.

    • GetURLContents, který stáhne obsah každý web a vrátí obsah jako bajtové pole.

    • DisplayResults, který zobrazuje počet bajtů v bajtové pole pro každou adresu URL.

    Zkopírujte následující čtyři metody a vložte je pod startButton_Click obslužné rutiny události MainWindow.xaml.vb nebo MainWindow.xaml.cs.

    Private Sub SumPageSizes()
    
        ' Make a list of web addresses. 
        Dim urlList As List(Of String) = SetUpURLList()
    
        Dim total = 0
        For Each url In urlList
            ' GetURLContents returns the contents of url as a byte array. 
            Dim urlContents As Byte() = GetURLContents(url)
    
            DisplayResults(url, urlContents)
    
            ' Update the total.
            total += urlContents.Length
        Next 
    
        ' Display the total count for all of the web addresses.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "Total bytes returned:  {0}" & vbCrLf, total)
    End Sub 
    
    
    Private Function SetUpURLList() As List(Of String)
    
        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function 
    
    
    Private Function GetURLContents(url As String) As Byte()
    
        ' The downloaded resource ends up in the variable named content. 
        Dim content = New MemoryStream()
    
        ' Initialize an HttpWebRequest for the current URL. 
        Dim webReq = CType(WebRequest.Create(url), HttpWebRequest)
    
        ' Send the request to the Internet resource and wait for 
        ' the response. 
        ' Note: you can't use HttpWebRequest.GetResponse in a Windows Store app. 
        Using response As WebResponse = webReq.GetResponse()
            ' Get the data stream that is associated with the specified URL. 
            Using responseStream As Stream = response.GetResponseStream()
                ' Read the bytes in responseStream and copy them to content.  
                responseStream.CopyTo(content)
            End Using 
        End Using 
    
        ' Return the result as a byte array. 
        Return content.ToArray()
    End Function 
    
    
    Private Sub DisplayResults(url As String, content As Byte())
    
        ' Display the length of each website. The string format  
        ' is designed to be used with a monospaced font, such as 
        ' Lucida Console or Global Monospace. 
        Dim bytes = content.Length
        ' Strip off the "http://". 
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub
    
    private void SumPageSizes()
    {
        // Make a list of web addresses.
        List<string> urlList = SetUpURLList(); 
    
        var total = 0;
        foreach (var url in urlList)
        {
            // GetURLContents returns the contents of url as a byte array. 
            byte[] urlContents = GetURLContents(url);
    
            DisplayResults(url, urlContents);
    
            // Update the total.
            total += urlContents.Length;
        }
    
        // Display the total count for all of the web addresses.
        resultsTextBox.Text += 
            string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
    }
    
    
    private List<string> SetUpURLList()
    {
        var urls = new List<string> 
        { 
            "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
            "https://msdn.microsoft.com",
            "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
            "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
            "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
            "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
            "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
            "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
            "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
            "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
        };
        return urls;
    }
    
    
    private byte[] GetURLContents(string url)
    {
        // The downloaded resource ends up in the variable named content. 
        var content = new MemoryStream();
    
        // Initialize an HttpWebRequest for the current URL. 
        var webReq = (HttpWebRequest)WebRequest.Create(url);
    
        // Send the request to the Internet resource and wait for 
        // the response. 
        // Note: you can't use HttpWebRequest.GetResponse in a Windows Store app. 
        using (WebResponse response = webReq.GetResponse())
        {
            // Get the data stream that is associated with the specified URL. 
            using (Stream responseStream = response.GetResponseStream())
            {
                // Read the bytes in responseStream and copy them to content.  
                responseStream.CopyTo(content);
            }
        }
    
        // Return the result as a byte array. 
        return content.ToArray();
    }
    
    
    private void DisplayResults(string url, byte[] content)
    {
        // Display the length of each website. The string format  
        // is designed to be used with a monospaced font, such as 
        // Lucida Console or Global Monospace. 
        var bytes = content.Length;
        // Strip off the "http://".
        var displayURL = url.Replace("http://", "");
        resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
    }
    

Chcete-li otestovat synchronní řešení

  • Zvolte klávesu F5, chcete-li spustit program a pak zvolte Start tlačítko.

    By se měl zobrazit výstup, který se podobá následující seznam.

    msdn.microsoft.com/library/windows/apps/br211380.aspx        383832
    msdn.microsoft.com                                            33964
    msdn.microsoft.com/en-us/library/hh290136.aspx               225793
    msdn.microsoft.com/en-us/library/ee256749.aspx               143577
    msdn.microsoft.com/en-us/library/hh290138.aspx               237372
    msdn.microsoft.com/en-us/library/hh290140.aspx               128279
    msdn.microsoft.com/en-us/library/dd470362.aspx               157649
    msdn.microsoft.com/en-us/library/aa578028.aspx               204457
    msdn.microsoft.com/en-us/library/ms404677.aspx               176405
    msdn.microsoft.com/en-us/library/ff730837.aspx               143474
    
    Total bytes returned:  1834802
    
    Control returned to startButton_Click.
    

    Všimněte si, že trvá několik sekund zobrazit počty.Během této doby je blokován vlákno uživatelského rozhraní a bude čekat požadované prostředky ke stažení.V důsledku toho nelze přesunout, maximalizovat, minimalizovat nebo dokonce zavřete okno zobrazení po zvolení Start tlačítko.Tyto snahy se nezdaří, dokud počty bytů začnou objevovat.Pokud web nereaguje, máte nenasvědčuje tomu, ze kterého serveru se nezdařilo.Je obtížné i ukončit čekání a ukončete program.

    Porovnejte toto chování Příklad asynchronní řešení.

Chcete-li převést GetURLContents asynchronní metody

  1. Převést synchronní řešení asynchronní řešení, je nejvhodnější místo pro spuštění v GetURLContents protože volání HttpWebRequest metoda GetResponse a Stream metoda CopyTo se, kde aplikace přistupuje k webu.Rozhraní.NET Framework usnadňuje převod zadáním asynchronní verze obou metod.

    Další informace o metodách, které se používají v GetURLContents, viz WebRequest.

    [!POZNÁMKA]

    Postupujte podle následujících kroků v tomto návodu zobrazí několik chyby kompilátoru.Můžete je ignorovat a pokračovat v tomto návodu.

    Změnit metodu, která je volána v třetí řádek GetURLContents z GetResponse na asynchronní, podle úloh GetResponseAsync metoda.

    Using response As WebResponse = webReq.GetResponseAsync()
    
    using (WebResponse response = webReq.GetResponseAsync())
    
  2. GetResponseAsyncVrátí Task.V tomto případě úloh návratové proměnné, TResult, má typ WebResponse.Úkol je promise vyrábět skutečné WebResponse objektu poté, co byla stažena požadovaná data a má po dokončení spuštění úlohy.

    Načíst WebResponse hodnotu z úlohy, použije Await (Visual Basic) nebo vyčkání operátor (C#) k volání GetResponseAsync, jak ukazuje následující kód.

    Using response As WebResponse = Await webReq.GetResponseAsync()
    
    using (WebResponse response = await webReq.GetResponseAsync())
    

    Operátor await pozastaví provádění aktuální metody GetURLContents, dokud awaited úkol je dokončen.Do té doby vrátí se řízení volající aktuální metody.V tomto příkladu je metoda aktuální GetURLContents, a volající se SumPageSizes.Pokud bude úkol dokončen, přislíbená WebResponse objekt je jako hodnota awaited úloh a jejich přiřazení proměnné response.

    Předchozí příkaz lze rozdělit do následující dva příkazy k objasnění, co se stane.

    'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync() 
    'Using response As WebResponse = Await responseTask
    
    //Task<WebResponse> responseTask = webReq.GetResponseAsync(); 
    //using (WebResponse response = await responseTask)
    

    The call to webReq.GetResponseAsync returns a Task(Of WebResponse) or Task<WebResponse>.Operátor await u úkolu k načtení a potom WebResponse hodnotu.

    Je-li asynchronní metody činnost není závislý na dokončení úkolu, metoda můžete pokračovat práce mezi tyto dva příkazy po volání asynchronní metody a dříve, než je použit operátor await.Příklady naleznete v tématech Postupy: Paralelní provádění vícenásobných webových dotazů pomocí modifikátoru Async a operátoru Await (C# and Visual Basic) a Postupy: Rozšíření návodu asynchronních úloh pomocí metody Task.WhenAll (C# and Visual Basic).

  3. Protože jste přidali Await nebo await dojde k chybě kompilátoru operátor v předchozím kroku.Operátor lze použít pouze v metodách, které jsou označeny asynchronní (Visual Basic) nebo asynchronní modifikátor (C#).Ignorovat chyby a opakujte kroky převodu nahradit volání CopyTo s voláním CopyToAsync.

    • Změnit název metody, která je volána pro CopyToAsync.

    • CopyTo Nebo CopyToAsync metoda zkopíruje bajtů na jeho argument contenta nevrací výstižnější.Synchronní verze volání CopyTo je jednoduchý příkaz, který nevrací hodnotu.Asynchronní verze CopyToAsync, vrátí Task.Úkol jako "Task(void)" a umožňuje metoda, která má být očekávané blahopřání.Použít Await nebo await k volání CopyToAsync, jak ukazuje následující kód.

      Await responseStream.CopyToAsync(content)
      
      await responseStream.CopyToAsync(content);
      

      Předchozí příkaz zkrátí následující dva řádky kódu.

      ' CopyToAsync returns a Task, not a Task<T>. 
      'Dim copyTask As Task = responseStream.CopyToAsync(content) 
      
      ' When copyTask is completed, content contains a copy of 
      ' responseStream. 
      'Await copyTask
      
      // CopyToAsync returns a Task, not a Task<T>. 
      //Task copyTask = responseStream.CopyToAsync(content); 
      
      // When copyTask is completed, content contains a copy of 
      // responseStream. 
      //await copyTask;
      
  4. Všechna tato zůstane prováděnou GetURLContents je upravit podpis metody.Můžete použít Await nebo await operátor pouze v metodách, které jsou označeny asynchronní (Visual Basic) nebo asynchronní modifikátor (C#).Přidat modifikátor k označení metody jako asynchronní metody, jak ukazuje následující kód.

    Private Async Function GetURLContents(url As String) As Byte()
    
    private async byte[] GetURLContents(string url)
    
  5. Návratový typ asynchronní metody mohou být pouze Task, Task, nebo void v jazyce C#.V jazyce Visual Basic musí být metoda Function , který vrací Task nebo Task(Of T), nebo metoda musí být Sub.Obvykle Sub metody (Visual Basic) nebo návratový typ void (C#) se používá pouze v asynchronní obslužnou rutinu, kde Sub nebo void je požadován.V ostatních případech použijte Task(T) metoda completed, má-li vrátit nebo vrátit zadejte příkaz, který vrací hodnotu T a použít Task pokud dokončené metoda nevrací hodnotu smysluplné.Si lze představit Task návratový typ jako "Task(void)."

    Další informace naleznete v tématu Asynchronní návratové typy (C# and Visual Basic).

    Metoda GetURLContents má příkaz return a příkaz vrátí pole bajtů.Návratový typ verze asynchronní tedy Task(T), kde T je bajtové pole.Proveďte následující změny v podpis metody:

    • Změňte návratový typ pro Task(Of Byte()) (Visual Basic) nebo Task<byte[]> (C#).

    • Dle úmluvy asynchronní metody mají názvy, které končí "Asynchronní," přejmenovat tak, aby metoda GetURLContentsAsync.

    Následující kód znázorňuje tyto změny.

    Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())
    
    private async Task<byte[]> GetURLContentsAsync(string url)
    

    Tyto několika jednoduchými změnami převod GetURLContents asynchronní metody je dokončena.

Chcete-li převést SumPageSizes asynchronní metody

  1. Opakujte kroky z předchozího postupu pro SumPageSizes.Nejprve změnit volání GetURLContents na asynchronní volání.

    • Změnit název metody, která je volána z GetURLContents na GetURLContentsAsync, pokud jste tak již neučinili.

    • Použít Await nebo await k úkolu, GetURLContentsAsync vrátí k získání byte pole hodnota.

    Následující kód znázorňuje tyto změny.

    Dim urlContents As Byte() = Await GetURLContentsAsync(url)
    
    byte[] urlContents = await GetURLContentsAsync(url);
    

    Předchozí přiřazení zkrátí následující dva řádky kódu.

    ' GetURLContentsAsync returns a task. At completion, the task 
    ' produces a byte array. 
    'Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url) 
    'Dim urlContents As Byte() = Await getContentsTask
    
    // GetURLContentsAsync returns a Task<T>. At completion, the task 
    // produces a byte array. 
    //Task<byte[]> getContentsTask = GetURLContentsAsync(url); 
    //byte[] urlContents = await getContentsTask;
    
  2. Proveďte následující změny v signatury metody:

    • Označit metodu s Async nebo async modifikátor.

    • Přidáte "Asynchronní" název metody.

    • Existuje totiž žádný úkol návratové proměnné, T, tentokrát SumPageSizesAsync nevrací hodnotu T.(Metoda má č Return nebo return příkaz.) Metoda však musí vrátit Task za awaitable.Proto proveďte jednu z následujících změn:

      • V jazyce Visual Basic změnit typ metody z Sub na Function.Návratový typ funkce je Task.

      • V jazyce C#, změňte návratový typ metody z void na Task.

    Následující kód znázorňuje tyto změny.

    Private Async Function SumPageSizesAsync() As Task
    
    private async Task SumPageSizesAsync()
    

    Převod z SumPageSizes na SumPageSizesAsync je dokončena.

Chcete-li převést startButton_Click asynchronní metody

  1. V obslužné rutině události změnit název volané metody z SumPageSizes na SumPageSizesAsync, pokud jste tak již neučinili.

  2. Protože SumPageSizesAsync je asynchronní metody, změňte kód v obslužné rutině události, kde čekají na výsledek.

    Volání SumPageSizesAsync zrcadlí volání CopyToAsync v GetURLContentsAsync.Volání vrátí Task, nikoli Task(T).

    Stejně jako v předchozích postupech lze převést volání pomocí jednoho příkazu nebo dva příkazy.Následující kód znázorňuje tyto změny.

    '' One-step async call.
    Await SumPageSizesAsync()
    
    ' Two-step async call. 
    'Dim sumTask As Task = SumPageSizesAsync() 
    'Await sumTask
    
    // One-step async call.
    await SumPageSizesAsync();
    
    // Two-step async call. 
    //Task sumTask = SumPageSizesAsync(); 
    //await sumTask;
    
  3. Chcete-li zabránit omylem nutnosti opětovného zadávání operace, přidejte následující příkaz do horní části startButton_Click Chcete-li zakázat Start tlačítko.

    ' Disable the button until the operation is complete.
    startButton.IsEnabled = False
    
    // Disable the button until the operation is complete.
    startButton.IsEnabled = false;
    

    Chcete-li znovu povolit tlačítko na konci obslužnou rutinu události.

    ' Reenable the button in case you want to run the operation again.
    startButton.IsEnabled = True
    
    // Reenable the button in case you want to run the operation again.
    startButton.IsEnabled = true;
    

    Další informace o vícenásobnému přístupu naleznete v tématu Podpora vícenásobného přístupu v aplikacích s modifikátorem Async (C# a Visual Basic).

  4. Nakonec přidejte Async nebo async modifikátor deklarace tak, že lze očekávat obslužné rutiny události SumPagSizesAsync.

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
    
    private async void startButton_Click(object sender, RoutedEventArgs e)
    

    Obvykle se nezmění názvy obslužných rutin událostí.Návratový typ není změněn na Task protože obslužné rutiny událostí musí vrátit void v jazyce C# nebo Sub procedury v jazyce Visual Basic.Proto návratový typ pro Task.

    Převod projektu pro asynchronní synchronní zpracování bylo dokončeno.

Chcete-li otestovat asynchronní řešení

  1. Zvolte klávesu F5, chcete-li spustit program a pak zvolte Start tlačítko.

  2. By se měl zobrazit výstup podobný následujícímu výstupu synchronní řešení.Všimněte si však tyto rozdíly.

    • Výsledky všech událostem ve stejnou dobu, po dokončení zpracování.Například oba programy obsahovat řádek v startButton_Click , vymaže textové pole.Záměrem je vymazat textové pole mezi spustí, pokud se rozhodnete Start tlačítko podruhé, poté, co se objevila jednu sadu výsledků.Synchronní verze textového pole není zaškrtnuto, těsně před udávají se podruhé po dokončení stažení a vlákno uživatelského rozhraní je zdarma k provedení jiné práce.Asynchronní verze textového pole vymaže okamžitě poté, co zvolíte Start tlačítko.

    • Co je nejdůležitější vlákno uživatelského rozhraní není zablokována soubory ke stažení.Můžete přesunout nebo změnit velikost okna během stahování webové prostředky, počítáno a zobrazeny.Je-li jeden z webových stránek je pomalý nebo neodpovídá, můžete zrušit operaci výběrem Zavřít tlačítko (x červené pole v pravém horním rohu).

Chcete-li nahradit metody GetURLContentsAsync metody rozhraní.NET Framework

  1. 4.5 Rozhraní .NET Framework poskytuje mnoho asynchronní metody, které můžete použít.Jeden z nich, HttpClient metoda GetByteArrayAsync(String), nemá přesně co potřebujete pro tento návod.Můžete se místo GetURLContentsAsync metodu, kterou jste vytvořili v předchozí proceduře.

    Prvním krokem je vytvoření HttpClient objektu v metodě SumPageSizesAsync.Přidejte následující deklaraci při spuštění metody.

    ' Declare an HttpClient object and increase the buffer size. The 
    ' default buffer size is 65,536. 
    Dim client As HttpClient =
        New HttpClient() With {.MaxResponseContentBufferSize = 1000000}
    
    // Declare an HttpClient object and increase the buffer size. The 
    // default buffer size is 65,536.
    HttpClient client =
        new HttpClient() { MaxResponseContentBufferSize = 1000000 };
    
  2. V SumPageSizesAsync, nahradit volání do GetURLContentsAsync metodu pomocí volání HttpClient metoda.

    Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
    byte[] urlContents = await client.GetByteArrayAsync(url);               
    
  3. Odebrat nebo poznámky, GetURLContentsAsync metodu, kterou jste napsali.

  4. Zvolte klávesu F5, chcete-li spustit program a pak zvolte Start tlačítko.

    Chování této verze projektu by měla odpovídat chování, které popisuje postup "Chcete-li otestovat asynchronní řešení", ale s i menším úsilím od vás.

Příklad

Následující kód obsahuje kompletní příklad převodu synchronního na asynchronní řešení pomocí asynchronní GetURLContentsAsync metodu, kterou jste napsali.Všimněte si, že silně připomíná původní synchronní řešení.

' Add the following Imports statements, and add a reference for System.Net.Http. 
Imports System.Net.Http
Imports System.Net
Imports System.IO

Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click

        ' Disable the button until the operation is complete.
        startButton.IsEnabled = False

        resultsTextBox.Clear()

        '' One-step async call.
        Await SumPageSizesAsync()

        ' Two-step async call. 
        'Dim sumTask As Task = SumPageSizesAsync() 
        'Await sumTask

        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click." 

        ' Reenable the button in case you want to run the operation again.
        startButton.IsEnabled = True 
    End Sub 


    Private Async Function SumPageSizesAsync() As Task

        ' Make a list of web addresses. 
        Dim urlList As List(Of String) = SetUpURLList()

        Dim total = 0
        For Each url In urlList
            Dim urlContents As Byte() = Await GetURLContentsAsync(url)

            ' The previous line abbreviates the following two assignment statements. 

            ' GetURLContentsAsync returns a task. At completion, the task 
            ' produces a byte array. 
            'Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url) 
            'Dim urlContents As Byte() = Await getContentsTask

            DisplayResults(url, urlContents)

            ' Update the total.
            total += urlContents.Length
        Next 

        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    End Function 


    Private Function SetUpURLList() As List(Of String)

        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function 


    Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())

        ' The downloaded resource ends up in the variable named content. 
        Dim content = New MemoryStream()

        ' Initialize an HttpWebRequest for the current URL. 
        Dim webReq = CType(WebRequest.Create(url), HttpWebRequest)

        ' Send the request to the Internet resource and wait for 
        ' the response. 
        Using response As WebResponse = Await webReq.GetResponseAsync()

            ' The previous statement abbreviates the following two statements. 

            'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync() 
            'Using response As WebResponse = Await responseTask 

            ' Get the data stream that is associated with the specified URL. 
            Using responseStream As Stream = response.GetResponseStream()
                ' Read the bytes in responseStream and copy them to content.  
                Await responseStream.CopyToAsync(content)

                ' The previous statement abbreviates the following two statements. 

                ' CopyToAsync returns a Task, not a Task<T>. 
                'Dim copyTask As Task = responseStream.CopyToAsync(content) 

                ' When copyTask is completed, content contains a copy of 
                ' responseStream. 
                'Await copyTask 
            End Using 
        End Using 

        ' Return the result as a byte array. 
        Return content.ToArray()
    End Function 


    Private Sub DisplayResults(url As String, content As Byte())

        ' Display the length of each website. The string format  
        ' is designed to be used with a monospaced font, such as 
        ' Lucida Console or Global Monospace. 
        Dim bytes = content.Length
        ' Strip off the "http://". 
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub 

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 the following using directives, and add a reference for System.Net.Http. 
using System.Net.Http;
using System.IO;
using System.Net;

namespace AsyncExampleWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Disable the button until the operation is complete.
            startButton.IsEnabled = false;

            resultsTextBox.Clear();

            // One-step async call.
            await SumPageSizesAsync();

            // Two-step async call. 
            //Task sumTask = SumPageSizesAsync(); 
            //await sumTask;

            resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";

            // Reenable the button in case you want to run the operation again.
            startButton.IsEnabled = true;
        }


        private async Task SumPageSizesAsync()
        {
            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();

            var total = 0;

            foreach (var url in urlList)
            {
                byte[] urlContents = await GetURLContentsAsync(url);

                // The previous line abbreviates the following two assignment statements. 

                // GetURLContentsAsync returns a Task<T>. At completion, the task 
                // produces a byte array. 
                //Task<byte[]> getContentsTask = GetURLContentsAsync(url); 
                //byte[] urlContents = await getContentsTask;

                DisplayResults(url, urlContents);

                // Update the total.          
                total += urlContents.Length;
            }
            // Display the total count for all of the websites.
            resultsTextBox.Text +=
                string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
        }


        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            };
            return urls;
        }


        private async Task<byte[]> GetURLContentsAsync(string url)
        {
            // The downloaded resource ends up in the variable named content. 
            var content = new MemoryStream();

            // Initialize an HttpWebRequest for the current URL. 
            var webReq = (HttpWebRequest)WebRequest.Create(url);

            // Send the request to the Internet resource and wait for 
            // the response.                 
            using (WebResponse response = await webReq.GetResponseAsync())

            // The previous statement abbreviates the following two statements. 

            //Task<WebResponse> responseTask = webReq.GetResponseAsync(); 
            //using (WebResponse response = await responseTask)
            {
                // Get the data stream that is associated with the specified url. 
                using (Stream responseStream = response.GetResponseStream())
                {
                    // Read the bytes in responseStream and copy them to content. 
                    await responseStream.CopyToAsync(content);

                    // The previous statement abbreviates the following two statements. 

                    // CopyToAsync returns a Task, not a Task<T>. 
                    //Task copyTask = responseStream.CopyToAsync(content); 

                    // When copyTask is completed, content contains a copy of 
                    // responseStream. 
                    //await copyTask;
                }
            }
            // Return the result as a byte array. 
            return content.ToArray();
        }


        private void DisplayResults(string url, byte[] content)
        {
            // Display the length of each website. The string format  
            // is designed to be used with a monospaced font, such as 
            // Lucida Console or Global Monospace. 
            var bytes = content.Length;
            // Strip off the "http://".
            var displayURL = url.Replace("http://", "");
            resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
        }
    }
}

Následující kód obsahuje kompletní příklad řešení, které používá HttpClient metoda, GetByteArrayAsync.

' Add the following Imports statements, and add a reference for System.Net.Http. 
Imports System.Net.Http
Imports System.Net
Imports System.IO

Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click

        resultsTextBox.Clear()

        ' Disable the button until the operation is complete.
        startButton.IsEnabled = False 

        ' One-step async call.
        Await SumPageSizesAsync()

        '' Two-step async call. 
        'Dim sumTask As Task = SumPageSizesAsync() 
        'Await sumTask

        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click." 

        ' Reenable the button in case you want to run the operation again.
        startButton.IsEnabled = True 
    End Sub 


    Private Async Function SumPageSizesAsync() As Task

        ' Declare an HttpClient object and increase the buffer size. The 
        ' default buffer size is 65,536. 
        Dim client As HttpClient =
            New HttpClient() With {.MaxResponseContentBufferSize = 1000000}

        ' Make a list of web addresses. 
        Dim urlList As List(Of String) = SetUpURLList()

        Dim total = 0
        For Each url In urlList
            ' GetByteArrayAsync returns a task. At completion, the task 
            ' produces a byte array. 
            Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)

            ' The following two lines can replace the previous assignment statement. 
            'Dim getContentsTask As Task(Of Byte()) = client.GetByteArrayAsync(url) 
            'Dim urlContents As Byte() = Await getContentsTask

            DisplayResults(url, urlContents)

            ' Update the total.
            total += urlContents.Length
        Next 

        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    End Function 


    Private Function SetUpURLList() As List(Of String)

        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function 


    Private Sub DisplayResults(url As String, content As Byte())

        ' Display the length of each website. The string format  
        ' is designed to be used with a monospaced font, such as 
        ' Lucida Console or Global Monospace. 
        Dim bytes = content.Length
        ' Strip off the "http://". 
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub 

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 the following using directives, and add a reference for System.Net.Http. 
using System.Net.Http;
using System.IO;
using System.Net;


namespace AsyncExampleWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            resultsTextBox.Clear();

            // Disable the button until the operation is complete.
            startButton.IsEnabled = false;

            // One-step async call.
            await SumPageSizesAsync();

            //// Two-step async call. 
            //Task sumTask = SumPageSizesAsync(); 
            //await sumTask;

            resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";

            // Reenable the button in case you want to run the operation again.
            startButton.IsEnabled = true;
        }


        private async Task SumPageSizesAsync()
        {
            // Declare an HttpClient object and increase the buffer size. The 
            // default buffer size is 65,536.
            HttpClient client =
                new HttpClient() { MaxResponseContentBufferSize = 1000000 };

            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();

            var total = 0;

            foreach (var url in urlList)
            {
                // GetByteArrayAsync returns a task. At completion, the task 
                // produces a byte array. 
                byte[] urlContents = await client.GetByteArrayAsync(url);               

                // The following two lines can replace the previous assignment statement. 
                //Task<byte[]> getContentsTask = client.GetByteArrayAsync(url); 
                //byte[] urlContents = await getContentsTask;

                DisplayResults(url, urlContents);

                // Update the total.
                total += urlContents.Length;
            }

            // Display the total count for all of the websites.
            resultsTextBox.Text +=
                string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
        }


        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            };
            return urls;
        }


        private void DisplayResults(string url, byte[] content)
        {
            // Display the length of each website. The string format  
            // is designed to be used with a monospaced font, such as 
            // Lucida Console or Global Monospace. 
            var bytes = content.Length;
            // Strip off the "http://".
            var displayURL = url.Replace("http://", "");
            resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
        }
    }
}

Viz také

Úkoly

Postupy: Rozšíření návodu asynchronních úloh pomocí metody Task.WhenAll (C# and Visual Basic)

Postupy: Paralelní provádění vícenásobných webových dotazů pomocí modifikátoru Async a operátoru Await (C# and Visual Basic)

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

Referenční dokumentace

async (Referenční dokumentace jazyka C#)

await – – operátor (Referenční dokumentace jazyka C#)

Await – operátor (Visual Basic)

Async (Visual Basic)

Koncepty

Asynchronní programování pomocí modifikátoru Async a operátoru Await (C# a Visual Basic)

Asynchronní návratové typy (C# and Visual Basic)

Použití modifikátoru Async pro přístup k souborům (C# a Visual Basic)

Další zdroje

Asynchronní vzorku: Přístup k webové návod (C# a Visual Basic)

Orientované asynchronní programování (KOHOUT)

Quickstart: použití operátoru await pro asynchronní programování