Bagikan melalui


Alur Kontrol dalam Program Asinkron (Visual Basic)

Anda dapat menulis dan memelihara program asinkron dengan lebih mudah dengan menggunakan Async kata kunci dan Await . Namun, hasilnya mungkin mengejutkan Anda jika Anda tidak memahami bagaimana program Anda beroperasi. Topik ini melacak alur kontrol melalui program asinkron sederhana untuk menunjukkan kepada Anda ketika kontrol berpindah dari satu metode ke metode lain dan informasi apa yang ditransfer setiap kali.

Nota

Kata kunci Async serta Await diperkenalkan pada Visual Studio 2012.

Secara umum, Anda menandai metode yang berisi kode asinkron dengan pengubah Asinkron . Dalam metode yang ditandai dengan pengubah asinkron, Anda dapat menggunakan operator Tunggu (Visual Basic) untuk menentukan di mana metode berhenti sejenak untuk menunggu proses asinkron yang disebut selesai. Untuk informasi selengkapnya, lihat Pemrograman Asinkron dengan Asinkron dan Tunggu (Visual Basic).

Contoh berikut menggunakan metode asinkron untuk mengunduh konten situs web tertentu sebagai string dan untuk menampilkan panjang string. Contohnya berisi dua metode berikut.

  • startButton_Click, yang memanggil AccessTheWebAsync dan menampilkan hasilnya.

  • AccessTheWebAsync, yang mengunduh konten situs web sebagai string dan mengembalikan panjang string. AccessTheWebAsync menggunakan metode asinkron HttpClient , GetStringAsync(String), untuk mengunduh konten.

Baris tampilan bernomor muncul di titik strategis di seluruh program untuk membantu Anda memahami bagaimana program berjalan dan menjelaskan apa yang terjadi di setiap titik yang ditandai. Garis tampilan diberi label "ONE" hingga "SIX." Label mewakili urutan program mencapai baris kode ini.

Kode berikut menunjukkan kerangka program.

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 &=
            vbCrLf & $"Length of the downloaded string: {contentLength}." & vbCrLf

    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://learn.microsoft.com")

        ' THREE
        Dim urlContents As String = Await getStringTask

        ' FIVE
        Return urlContents.Length
    End Function

End Class

Masing-masing lokasi berlabel, "ONE" hingga "SIX," menampilkan informasi tentang status program saat ini. Hasil berikut telah diproduksi.

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.

Menyiapkan Program

Anda dapat mengunduh kode yang digunakan topik ini dari MSDN, atau Anda dapat membuatnya sendiri.

Nota

Untuk menjalankan contoh, Anda harus memasang Visual Studio 2012 atau yang lebih baru dan .NET Framework 4.5 atau yang lebih baru di komputer Anda.

Unduh Programnya

Anda dapat mengunduh aplikasi untuk topik ini dari Sampel Asinkron: Alur Kontrol di Program Asinkron. Langkah-langkah berikut membuka dan menjalankan program.

  1. Buka zip file yang diunduh, lalu mulai Visual Studio.

  2. Pada bilah menu, pilih File, Buka, Proyek/Solusi.

  3. Navigasi ke folder yang menyimpan kode sampel yang tidak di-zip, buka file solusi (.sln), lalu pilih kunci F5 untuk membangun dan menjalankan proyek.

Bangun Program Sendiri

Proyek Windows Presentation Foundation (WPF) berikut berisi contoh kode untuk topik ini.

Untuk menjalankan proyek, lakukan langkah-langkah berikut:

  1. Mulai Visual Studio.

  2. Pada 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. Masukkan AsyncTracer sebagai nama proyek, lalu pilih tombol OK .

    Proyek baru muncul di Penjelajah Solusi.

  5. Di Editor Visual Studio Code, pilih tab MainWindow.xaml .

    Jika tab tidak terlihat, buka menu pintasan untuk MainWindow.xaml di Penjelajah Solusi, lalu pilih Tampilkan Kode.

  6. Dalam tampilan XAML MainWindow.xaml, ganti kode dengan kode berikut.

    <Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://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>
    

    Jendela sederhana yang berisi kotak teks dan tombol muncul di tampilan Desain MainWindow.xaml.

  7. Tambahkan referensi untuk System.Net.Http.

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

  9. Di MainWindow.xaml.vb , ganti kode dengan kode berikut.

    ' 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://learn.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
    
  10. Pilih tombol F5 untuk menjalankan program, lalu pilih tombol Mulai .

    Output berikut akan muncul:

    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.
    

Melacak Program

Langkah SATU dan DUA

Dua baris tampilan pertama melacak jalur saat startButton_Click memanggil AccessTheWebAsync, dan AccessTheWebAsync memanggil metode HttpClient asinkron GetStringAsync(String). Gambar berikut menunjukkan panggilan dari satu metode ke metode lain.

Langkah SATU dan DUA

Jenis pengembalian dari AccessTheWebAsync dan client.GetStringAsync adalah Task<TResult>. Untuk AccessTheWebAsync, TResult adalah bilangan bulat. Untuk GetStringAsync, TResult adalah string. Untuk informasi selengkapnya tentang jenis pengembalian metode asinkron, lihat Jenis Pengembalian Asinkron (Visual Basic).

Metode asinkron yang mengembalikan tugas mengembalikan instans tugas saat kontrol bergeser kembali ke pemanggil. Pengendalian kembali dari metode asinkron ke pemanggilnya baik ketika operator Await ditemukan dalam metode yang dipanggil atau ketika metode yang dipanggil berakhir. Baris tampilan yang diberi label "THREE" hingga "SIX" menelusuri bagian dari proses ini.

Langkah TIGA

Dalam AccessTheWebAsync, metode GetStringAsync(String) asinkron dipanggil untuk mengunduh konten halaman web target. Kontrol kembali dari client.GetStringAsync ke AccessTheWebAsync ketika client.GetStringAsync kembali.

Metode client.GetStringAsync mengembalikan tugas berupa string yang ditetapkan ke variabel getStringTask di AccessTheWebAsync. Baris berikut dalam contoh program menunjukkan panggilan ke client.GetStringAsync dan penugasan.

Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com")

Anda dapat menganggap tugas sebagai janji oleh client.GetStringAsync untuk menghasilkan string aktual pada akhirnya. Sementara itu, jika AccessTheWebAsync memiliki pekerjaan yang harus dilakukan yang tidak bergantung pada string yang dijanjikan dari client.GetStringAsync, pekerjaan tersebut dapat dilanjutkan saat client.GetStringAsync menunggu. Dalam contoh, baris output berikut, yang diberi label "THREE," mewakili kesempatan untuk melakukan pekerjaan independen

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

Pernyataan berikut menghentikan sementara kemajuan dalam AccessTheWebAsync ketika getStringTask ditunggu.

Dim urlContents As String = Await getStringTask

Gambar berikut memperlihatkan proses kontrol dari client.GetStringAsync ke penugasan ke getStringTask dan dari pembuatan getStringTask ke penerapan operator Await.

Langkah 3

Ekspresi tunggu menunda AccessTheWebAsync hingga client.GetStringAsync mengembalikan nilai. Sementara itu, kontrol kembali ke pemanggil , AccessTheWebAsyncstartButton_Click.

Nota

Biasanya, Anda langsung menunggu panggilan ke metode asinkron. Misalnya, penetapan berikut dapat menggantikan kode sebelumnya yang membuat lalu menunggu getStringTask: Dim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")

Dalam topik ini, operator await diterapkan kemudian untuk mengakomodasi baris output yang menunjukkan alur kontrol dalam program.

Langkah EMPAT

Jenis pengembalian yang telah dinyatakan untuk AccessTheWebAsync adalah Task(Of Integer). Oleh karena itu, ketika AccessTheWebAsync ditangguhkan, ia mengembalikan tugas bilangan bulat ke startButton_Click. Anda perlu memahami bahwa tugas yang dikembalikan bukan getStringTask. Tugas yang dikembalikan adalah tugas baru berupa bilangan bulat yang mewakili apa yang masih harus dilakukan dalam metode yang ditangguhkan, AccessTheWebAsync. Tugas adalah janji dari AccessTheWebAsync untuk menghasilkan bilangan bulat ketika tugas selesai.

Pernyataan berikut menetapkan tugas ini ke getLengthTask variabel .

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

Seperti dalam AccessTheWebAsync, startButton_Click dapat melanjutkan pekerjaan yang tidak bergantung pada hasil tugas asinkron (getLengthTask) hingga tugas tersebut ditunggu. Baris output berikut mewakili pekerjaan tersebut:

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

Kemajuan pada startButton_Click ditangguhkan saat getLengthTask sedang menunggu. Pernyataan penugasan berikut menangguhkan startButton_Click hingga AccessTheWebAsync selesai.

Dim contentLength As Integer = Await getLengthTask

Dalam ilustrasi berikut, panah memperlihatkan alur kontrol dari ekspresi AccessTheWebAsync yang ditunggu ke penetapan nilai ke getLengthTask, diikuti dengan pemrosesan normal di startButton_Click hingga getLengthTask ditunggu.

Langkah FOUR

Langkah LIMA

Ketika client.GetStringAsync memberi sinyal bahwa itu selesai, pemrosesan di AccessTheWebAsync dibebaskan dari penangguhan dan dapat meneruskan pernyataan tunggu. Baris output berikut mewakili dimulainya kembali pemrosesan:

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

Operan dari pernyataan pengembalian, urlContents.Length, disimpan dalam tugas yang AccessTheWebAsync mengembalikan. Ekspresi tunggu mengambil nilai tersebut dari getLengthTask dalam startButton_Click.

Gambar berikut menunjukkan transfer kontrol setelah client.GetStringAsync (dan getStringTask) selesai.

Langkah FIVE

AccessTheWebAsync berjalan hingga selesai, dan kontrol kembali ke startButton_Click, yang menunggu penyelesaian.

Langkah ENAM

Ketika AccessTheWebAsync menunjukkan bahwa itu selesai, pemrosesan dapat dilanjutkan setelah pernyataan await di startButton_Async. Sebenarnya, tidak ada lagi yang perlu dilakukan oleh program tersebut.

Baris output berikut mewakili dimulainya kembali pemrosesan di startButton_Async:

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

Ekspresi tunggu mengambil dari getLengthTask nilai bilangan bulat yang menjadi operand dari pernyataan return di AccessTheWebAsync. Pernyataan berikut menetapkan nilai tersebut ke contentLength variabel .

Dim contentLength As Integer = Await getLengthTask

Gambar berikut menunjukkan pengembalian kontrol dari AccessTheWebAsync ke startButton_Click.

Langkah ENAM

Lihat juga