Panduan: Mengakses Web Menggunakan Async dan Await (Visual Basic)

Anda dapat menulis program asinkron dengan lebih mudah dan intuitif menggunakan fitur asinkron/tunggu. Anda dapat menulis kode asinkron yang terlihat seperti kode sinkron dan membiarkan pengompilasi menangani kesulitan fungsi panggilan balik serta kelanjutan yang biasanya diperlukan oleh kode asinkron.

Untuk informasi selengkapnya tentang fitur Async, lihat Pemrograman Asinkron dengan Async dan Await (Visual Basic).

Panduan ini dimulai dengan aplikasi Windows Presentation Foundation (WPF) sinkron yang menjumlahkan jumlah byte dalam daftar situs web. Panduan kemudian mengubah aplikasi ke solusi asinkron menggunakan fitur baru.

Anda dapat mengembangkan aplikasi dengan menyelesaikan panduan atau mengunduh sampel dari Browser Sampel .NET. Contoh kode ada dalam proyek SerialAsyncExample.

Dalam panduan ini, Anda menyelesaikan tugas berikut:

Lihat bagian Contoh untuk contoh asinkron lengkap.

Prasyarat

Visual Studio 2012 atau lebih baru harus diinstal pada komputer Anda. Untuk informasi selengkapnya, lihat halaman Unduhan Visual Studio.

Membuat aplikasi WPF

  1. Mulai Visual Studio.

  2. Di bilah menu, pilih File, Baru, Proyek.

    Kotak dialog Proyek Baru terbuka.

  3. Di panel Templat Terinstal, pilih Visual Basic, lalu pilih Aplikasi WPF dari daftar jenis proyek.

  4. Dalam kotak teks Nama, masukkan AsyncExampleWPF, lalu pilih tombol OK.

    Proyek baru muncul di Penjelajah Solusi.

Mendesain WPF MainWindow sederhana

  1. Di editor Visual Studio Code, pilih tab MainWindow.xaml.

  2. Jika jendela Kotak Alat tidak terlihat, buka menu Tampilan, lalu pilih Kotak Alat.

  3. Tambahkan kontrol Tombol dan kontrol Kotak Teks ke jendela MainWindow.

  4. Sorot kontrol Kotak Teks dan, di jendela Properti, atur nilai berikut:

    • Atur properti Nama ke resultsTextBox.

    • Atur properti Tinggi ke 250.

    • Atur properti Lebar ke 500.

    • Pada tab Teks, tentukan ukuran font monospace, seperti Lucida Console atau Global Monospace.

  5. Sorot kontrol Tombol dan, di jendela Properti, atur nilai berikut:

    • Atur properti Nama ke startButton.

    • Ubah nilai properti Konten dari Tombol ke Mulai.

  6. Posisikan kotak teks dan tombol sehingga keduanya muncul di jendela MainWindow.

    Untuk informasi selengkapnya tentang Perancang WPF XAML, lihat Membuat antarmuka pengguna menggunakan Perancang XAML.

Menambahkan referensi

  1. Di Penjelajah Solusi, sorot nama proyek Anda.

  2. Pada bilah menu, pilih Proyek, Tambahkan Referensi.

    Kotak dialog Manajer Referensi muncul.

  3. Di atas kotak dialog, verifikasikan bahwa proyek Anda menargetkan .NET Framework 4.5 atau lebih tinggi.

  4. Di area Rakitan, pilih Kerangka Kerja jika belum dipilih.

  5. Dalam daftar nama, pilih kotak centang System.Net.Http.

  6. Pilih tombol OK untuk menutup kotak dialog.

Menambahkan pernyataan Imports yang diperlukan

  1. Di Penjelajah Solusi, buka menu pintasan untuk MainWindow.xaml.vb, lalu pilih Tampilkan Kode.

  2. Tambahkan pernyataan Imports berikut pada bagian atas file kode jika belum ada.

    Imports System.Net.Http
    Imports System.Net
    Imports System.IO
    

Membuat aplikasi sinkron

  1. Di jendela desain, MainWindow.xaml, klik dua kali tombol Mulai untuk membuat penanganan aktivitas startButton_Click di MainWindow.xaml.vb.

  2. Di MainWindow.xaml.vb, salin kode berikut ke dalam isi startButton_Click:

    resultsTextBox.Clear()
    SumPageSizes()
    resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
    

    Kode memanggil metode yang mendorong aplikasi, SumPageSizes, dan menampilkan pesan saat kontrol mengembalikan ke startButton_Click.

  3. Kode untuk solusi sinkron berisi empat metode berikut:

    • SumPageSizes, yang mendapat daftar URL halaman web dari SetUpURLList lalu memanggil GetURLContents dan DisplayResults untuk memproses setiap URL.

    • SetUpURLList, yang membuat dan mengembalikan daftar alamat web.

    • GetURLContents, yang mengunduh konten dari setiap situs web dan mengembalikan konten sebagai array byte.

    • DisplayResults, yang menampilkan jumlah byte dalam array byte untuk setiap URL.

    Salin empat metode berikut, lalu tempelkan metode tersebut di bawah penanganan aktivitas startButton_Click di MainWindow.xaml.vb:

    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/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/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 "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub
    

Menguji solusi sinkron

  1. Pilih tombol F5 untuk menjalankan program, lalu pilih tombol Mulai.

    Output yang menyerupai daftar berikut harus muncul:

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

    Perhatikan bahwa dibutuhkan beberapa detik untuk menampilkan hitungan. Selama waktu itu, utas antarmuka pengguna diblokir saat utas antarmuka pengguna menunggu sumber daya yang diminta untuk diunduh. Akibatnya, Anda tidak dapat memindahkan, membesarkan, mengecilkan, atau menutup jendela setelah Anda memilih tombol Mulai. Upaya ini gagal hingga jumlah byte mulai muncul. Jika situs web tidak merespons, Anda tidak memiliki indikasi situs mana yang gagal. Bahkan sulit untuk berhenti menunggu dan menutup program.

Mengonversi GetURLContents ke metode asinkron

  1. Untuk mengonversi solusi sinkron ke solusi asinkron, tempat terbaik untuk memulai adalah di GetURLContents karena panggilan ke metode HttpWebRequest.GetResponse dan metode Stream.CopyTo ada di tempat aplikasi mengakses web. .NET Framework memudahkan konversi dengan menyediakan versi asinkron dari kedua metode.

    Untuk informasi selengkapnya tentang metode yang digunakan di GetURLContents, lihat WebRequest.

    Catatan

    Saat Anda mengikuti langkah-langkah dalam panduan ini, beberapa kesalahan pengompilasi muncul. Anda dapat mengabaikannya dan melanjutkan panduannya.

    Ubah metode yang disebut di baris ketiga GetURLContents dari GetResponse ke metode GetResponseAsync asinkron berbasis tugas.

    Using response As WebResponse = webReq.GetResponseAsync()
    
  2. GetResponseAsync mengembalikan Task<TResult>. Dalam kasus ini, variabel pengembalian tugas, TResult, memiliki jenis WebResponse. Tugas adalah janji untuk menghasilkan objek WebResponse aktual setelah data yang diminta telah diunduh dan tugas telah berjalan hingga selesai.

    Untuk mengambil nilai WebResponse dari tugas, terapkan operator Tunggu ke panggilan menjadi GetResponseAsync, seperti yang ditunjukkan kode berikut.

    Using response As WebResponse = Await webReq.GetResponseAsync()
    

    Operator Await menangguhkan eksekusi metode saat ini, GetURLContents, hingga tugas yang ditunggu selesai. Sementara itu, kontrol kembali ke pemanggil metode saat ini. Dalam contoh ini, metode saat ini adalah GetURLContents, dan pemanggil adalah SumPageSizes. Ketika tugas selesai, objek WebResponse yang dijanjikan diproduksi sebagai nilai tugas yang ditunggu dan ditetapkan ke variabel response.

    Pernyataan sebelumnya dapat dipisahkan menjadi dua pernyataan berikut untuk menjelaskan apa yang terjadi.

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

    Panggilan untuk webReq.GetResponseAsync mengembalikan Task(Of WebResponse) atau Task<WebResponse>. Kemudian operator Await diterapkan ke tugas untuk mengambil nilai WebResponse.

    Jika metode asinkron Anda memiliki pekerjaan yang harus dilakukan yang tidak bergantung pada penyelesaian tugas, metode dapat melanjutkan pekerjaan tersebut antara dua pernyataan ini, setelah panggilan ke metode asinkron dan sebelum operator tunggu diterapkan. Misalnya, lihat Cara: Membuat Beberapa Permintaan Web secara Paralel Menggunakan Async dan Await (Visual Basic) dan Cara: Memperluas Panduan Async Menggunakan Task.WhenAll (Visual Basic).

  3. Karena Anda menambahkan operator Await di langkah sebelumnya, kesalahan pengompilasi terjadi. Operator hanya dapat digunakan di metode yang ditandai dengan pengubah Async. Abaikan kesalahan saat Anda mengulangi langkah konversi untuk mengganti panggilan ke CopyTo dengan panggilan ke CopyToAsync.

    • Ubah nama metode yang dipanggil ke CopyToAsync.

    • Metode CopyTo atau CopyToAsync menyalin byte ke argumennya, content, dan tidak mengembalikan nilai yang bermakna. Dalam versi sinkron, panggilan ke CopyTo adalah pernyataan sederhana yang tidak mengembalikan nilai. Versi asinkron, CopyToAsync, mengembalikan Task. Tugas fungsi seperti Task(void)" dan memungkinkan metode untuk ditunggu. Terapkan Await atau await ke panggilan menjadi CopyToAsync, seperti yang ditunjukkan kode berikut.

      Await responseStream.CopyToAsync(content)
      

      Pernyataan sebelumnya menyingkat dua baris kode berikut.

      ' 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
      
  4. Yang masih harus dilakukan dalam GetURLContents adalah menyesuaikan tanda tangan metode. Anda hanya dapat menggunakan operator Await hanya di metode yang ditandai dengan pengubah Async. Tambahkan pengubah untuk menandai metode sebagai metode asinkron, seperti yang ditunjukkan kode berikut.

    Private Async Function GetURLContents(url As String) As Byte()
    
  5. Jenis pengembalian metode asinkron hanya dapat berupa Task, Task<TResult>. Dalam Visual Basic, metode harus berupa Function yang mengembalikan Task atau Task(Of T), atau metode harus berupa Sub. Biasanya. metode Sub hanya digunakan dalam penanganan aktivitas asinkron, ketika Sub diperlukan. Dalam kasus ini, Anda menggunakan Task(T) jika metode yang selesai memiliki pernyataan Kembali yang mengembalikan nilai jenis T, dan Anda menggunakan Task jika metode yang selesai tidak mengembalikan nilai yang bermakna.

    Untuk informasi selengkapnya, lihat Jenis Tampilan Asinkron (Visual Basic).

    Metode GetURLContents memiliki pernyataan pengembalian, dan pernyataan tersebut mengembalikan array byte. Oleh karena itu, jenis pengembalian versi asinkron adalah Task(T), dengan T merupakan array byte. Buat perubahan berikut dalam tanda tangan metode:

    • Ubah jenis pengembalian ke Task(Of Byte()).

    • Menurut konvensi, metode asinkron memiliki nama yang berakhiran "Async", maka ganti nama metode GetURLContentsAsync.

    Kode berikut menunjukkan perubahan ini.

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

    Dengan beberapa perubahan tersebut, konversi GetURLContents ke metode asinkron selesai.

Mengonversi SumPageSizes ke metode asinkron

  1. Ulangi langkah-langkah dari prosedur sebelumnya untuk SumPageSizes. Pertama, ubah panggilan ke GetURLContents menjadi panggilan asinkron.

    • Ubah nama metode yang disebut dari GetURLContents ke GetURLContentsAsync, jika Anda belum melakukannya.

    • Terapkan Await ke tugas yang GetURLContentsAsync kembalikan untuk mendapatkan nilai array byte.

    Kode berikut menunjukkan perubahan ini.

    Dim urlContents As Byte() = Await GetURLContentsAsync(url)
    

    Pernyataan sebelumnya menyingkat dua baris kode berikut.

    ' 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
    
  2. Buat perubahan berikut dalam tanda tangan metode:

    • Tandai metode dengan pengubah Async.

    • Tambahkan "Async" ke nama metode.

    • Tidak ada variabel pengembalian tugas, T, kali ini karena SumPageSizesAsync tidak mengembalikan nilai untuk T. (Metode tidak memiliki pernyataan Return.) Namun, metode harus mengembalikan Task agar dapat ditunggu. Oleh karena itu, ubah jenis metode dari Sub ke Function. Jenis pengembalian fungsi adalah Task.

    Kode berikut menunjukkan perubahan ini.

    Private Async Function SumPageSizesAsync() As Task
    

    Konversi SumPageSizes ke SumPageSizesAsync selesai.

Mengonversi startButton_Click ke metode asinkron

  1. Di penanganan aktivitas, ubah nama metode yang dipanggil dari SumPageSizes ke SumPageSizesAsync, jika Anda belum melakukannya.

  2. Karena SumPageSizesAsync adalah metode asinkron, ubah kode di penanganan aktivitas untuk menunggu hasilnya.

    Panggilan ke SumPageSizesAsync mencerminkan panggilan ke CopyToAsync dalam GetURLContentsAsync. Panggilan mengembalikan Task, bukan Task(T).

    Seperti dalam prosedur sebelumnya, Anda dapat mengonversi panggilan menggunakan satu pernyataan atau dua pernyataan. Kode berikut menunjukkan perubahan ini.

    ' One-step async call.
    Await SumPageSizesAsync()
    
    ' Two-step async call.
    Dim sumTask As Task = SumPageSizesAsync()
    Await sumTask
    
  3. Untuk mencegah masuknya kembali operasi secara tidak sengaja, tambahkan pernyataan berikut di atas startButton_Click untuk menonaktifkan tombol Mulai.

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

    Anda dapat mengaktifkan kembali tombol di akhir penanganan aktivitas.

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

    Untuk informasi selengkapnya tentang masuk kembali, lihat Menangani Masuk Kembali di Aplikasi Async (Visual Basic).

  4. Terakhir, tambahkan pengubah Async ke deklarasi sehingga penanganan aktivitas dapat menunggu SumPagSizesAsync.

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

    Biasanya, nama penanganan aktivitas tidak diubah. Jenis pengembalian tidak diubah ke Task karena penanganan aktivitas harus berupa prosedur Sub dalam Visual Basic.

    Konversi proyek dari pemrosesan sinkron ke asinkron selesai.

Menguji solusi asinkron

  1. Pilih tombol F5 untuk menjalankan program, lalu pilih tombol Mulai.

  2. Output yang menyerupai output solusi sinkron harus muncul. Namun, perhatikan perbedaan berikut.

    • Tidak semua hasil terjadi pada waktu bersamaan setelah pemrosesan selesai. Misalnya, kedua program berisi baris di startButton_Click yang membersihkan kotak teks. Niatnya adalah untuk menghapus kotak teks antara eksekusi jika Anda memilih tombol Mulai untuk kedua kalinya, setelah satu set hasil muncul. Dalam versi sinkron, kotak teks dibersihkan sebelum hitungan muncul untuk yang kedua kalinya, ketika unduhan selesai dan utas antarmuka pengguna bebas untuk melakukan pekerjaan lain. Dalam versi asinkron, kotak teks segera dibersihkan setelah Anda memilih tombol Mulai.

    • Yang terpenting, utas antarmuka pengguna tidak diblokir selama pengunduhan. Anda dapat memindahkan atau mengubah ukuran saat sumber daya web diunduh, dihitung, dan ditampilkan. Jika salah satu situs web lambat atau tidak merespons, Anda dapat membatalkan operasi dengan memilih tombol Tutup (x di bidang merah di sudut kanan atas).

Mengganti metode GetURLContentsAsync dengan metode .NET Framework

  1. .NET Framework menyediakan banyak metode asinkron yang dapat Anda gunakan. Salah satunya, metode HttpClient.GetByteArrayAsync(String), melakukan apa yang Anda butuhkan untuk panduan ini. Anda dapat menggunakannya daripada metode GetURLContentsAsync yang Anda buat dalam prosedur sebelumnya.

    Langkah pertama adalah membuat objek HttpClient di metode SumPageSizesAsync. Tambahkan deklarasi berikut di awal metode.

    ' 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}
    
  2. Di SumPageSizesAsync,, ganti panggilan ke metode GetURLContentsAsync Anda dengan panggilan ke metode HttpClient.

    Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
  3. Hapus atau komentari metode GetURLContentsAsync yang Anda tulis.

  4. Pilih tombol F5 untuk menjalankan program, lalu pilih tombol Mulai.

    Perilaku versi proyek ini harus sesuai dengan perilaku yang dijelaskan oleh prosedur "Untuk menguji solusi asinkron" tetapi dengan usaha yang sedikit dari Anda.

Contoh

Berikut adalah contoh lengkap solusi asinkron yang dikonversi menggunakan metode GetURLContentsAsync asinkron. Perhatikan bahwa solusi tersebut sangat mirip dengan aslinya, solusi sinkron.

' 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.

            '//<snippet21>
            ' 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/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/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 "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

End Class

Kode berikut berisi contoh lengkap solusi yang menggunakan metode HttpClient, yaitu 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/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/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 "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

End Class

Lihat juga