Bagikan melalui


Mulai Beberapa Tugas Asinkron dan Proses Saat Selesai (Visual Basic)

Dengan menggunakan Task.WhenAny, Anda dapat memulai beberapa tugas secara bersamaan dan memprosesnya satu per satu saat tugas selesai daripada memprosesnya dalam urutan dimulai.

Contoh berikut menggunakan kueri untuk membuat kumpulan tugas. Setiap tugas mengunduh konten situs web tertentu. Dalam setiap perulangan sementara, panggilan yang ditunggu untuk WhenAny mengembalikan tugas dalam kumpulan tugas yang menyelesaikan unduhannya terlebih dahulu. Tugas tersebut dihapus dari koleksi dan diproses. Perulangan diulang hingga koleksi tidak berisi lebih banyak tugas.

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.

Mengunduh Contoh

Anda dapat mengunduh proyek Windows Presentation Foundation (WPF) lengkap dari Async Sample: Fine Tuning Your Application lalu ikuti langkah-langkah berikut.

  1. Dekompresi file yang Anda unduh, lalu mulai Visual Studio.

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

  3. Dalam kotak dialog Buka Proyek , buka folder yang menyimpan kode sampel yang Anda dekompresi, lalu buka file solusi (.sln) untuk AsyncFineTuningVB.

  4. Di Penjelajah Solusi, buka menu pintasan untuk proyek ProcessTasksAsTheyFinish , lalu pilih Atur sebagai Proyek StartUp.

  5. Pilih kunci F5 untuk menjalankan proyek.

    Pilih tombol Ctrl+F5 untuk menjalankan proyek tanpa men-debugnya.

  6. Jalankan proyek beberapa kali untuk memverifikasi bahwa panjang yang diunduh tidak selalu muncul dalam urutan yang sama.

Jika Anda tidak ingin mengunduh proyek, Anda dapat meninjau file MainWindow.xaml.vb di akhir topik ini.

Membangun Contoh

Contoh ini menambahkan ke kode yang dikembangkan di Batalkan Tugas Asinkron Yang Tersisa setelah Satu Selesai (Visual Basic) dan menggunakan UI yang sama.

Untuk membuat contoh sendiri, langkah demi langkah, ikuti instruksi di bagian "Mengunduh Contoh", tetapi pilih CancelAfterOneTask sebagai Proyek StartUp. Tambahkan perubahan dalam topik ini ke metode AccessTheWebAsync dalam proyek tersebut. Perubahan ditandai dengan tanda bintang.

Proyek CancelAfterOneTask sudah menyertakan kueri yang, saat dijalankan, membuat kumpulan tugas. Setiap panggilan ke ProcessURLAsync dalam kode berikut mengembalikan Task<TResult> di mana TResult adalah bilangan bulat.

Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =  
    From url In urlList Select ProcessURLAsync(url, client, ct)  

Untuk membuat perubahan berikut pada metode AccessTheWebAsync di dalam file MainWindow.xaml.vb di proyek.

  • Jalankan kueri dengan menerapkan Enumerable.ToList alih-alih ToArray.

    Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()  
    
  • Tambahkan perulangan while yang melakukan langkah-langkah berikut untuk setiap tugas dalam kumpulan.

    1. Menunggu panggilan ke WhenAny untuk mengidentifikasi tugas pertama yang selesai diunduh dalam koleksi.

      Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)  
      
    2. Menghapus tugas tersebut dari koleksi.

      downloadTasks.Remove(finishedTask)  
      
    3. Menunggu finishedTask, yang dikembalikan oleh panggilan ke ProcessURLAsync. Variabel finishedTask adalah Task<TResult> di mana TReturn adalah bilangan bulat. Tugas sudah selesai, tetapi Anda menunggunya untuk mengambil panjang situs web yang diunduh, seperti yang ditunjukkan contoh berikut.

      Dim length = Await finishedTask  
      resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website:  {0}" & vbCrLf, length)  
      

Anda harus menjalankan proyek beberapa kali untuk memverifikasi bahwa panjang yang diunduh tidak selalu muncul dalam urutan yang sama.

Perhatian

Anda dapat menggunakan WhenAny dalam perulangan, seperti yang dijelaskan dalam contoh, untuk menyelesaikan masalah yang melibatkan sejumlah kecil tugas. Namun, pendekatan lain lebih efisien jika Anda memiliki sejumlah besar tugas untuk diproses. Untuk informasi dan contoh selengkapnya, lihat Memproses Tugas saat selesai.

Contoh Lengkap

Kode berikut adalah teks lengkap file MainWindow.xaml.vb untuk contoh. Tanda bintang menandai elemen yang ditambahkan untuk contoh ini.

Perhatikan bahwa Anda harus menambahkan referensi untuk System.Net.Http.

Anda dapat mengunduh proyek dari Sampel Asinkron: Menyempurnakan Aplikasi Anda.

' Add an Imports directive and a reference for System.Net.Http.  
Imports System.Net.Http  
  
' Add the following Imports directive for System.Threading.  
Imports System.Threading  
  
Class MainWindow  
  
    ' Declare a System.Threading.CancellationTokenSource.  
    Dim cts As CancellationTokenSource  
  
    Private Async Sub startButton_Click(sender As Object, e As RoutedEventArgs)  
  
        ' Instantiate the CancellationTokenSource.  
        cts = New CancellationTokenSource()  
  
        resultsTextBox.Clear()  
  
        Try  
            Await AccessTheWebAsync(cts.Token)  
            resultsTextBox.Text &= vbCrLf & "Downloads complete."  
  
        Catch ex As OperationCanceledException  
            resultsTextBox.Text &= vbCrLf & "Downloads canceled." & vbCrLf  
  
        Catch ex As Exception  
            resultsTextBox.Text &= vbCrLf & "Downloads failed." & vbCrLf  
        End Try  
  
        ' Set the CancellationTokenSource to Nothing when the download is complete.  
        cts = Nothing  
    End Sub  
  
    ' You can still include a Cancel button if you want to.  
    Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)  
  
        If cts IsNot Nothing Then  
            cts.Cancel()  
        End If  
    End Sub  
  
    ' Provide a parameter for the CancellationToken.  
    ' Change the return type to Task because the method has no return statement.  
    Async Function AccessTheWebAsync(ct As CancellationToken) As Task  
  
        Dim client As HttpClient = New HttpClient()  
  
        ' Call SetUpURLList to make a list of web addresses.  
        Dim urlList As List(Of String) = SetUpURLList()  
  
        ' ***Create a query that, when executed, returns a collection of tasks.  
        Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =  
            From url In urlList Select ProcessURLAsync(url, client, ct)  
  
        ' ***Use ToList to execute the query and start the download tasks.
        Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()  
  
        ' ***Add a loop to process the tasks one at a time until none remain.  
        While downloadTasks.Count > 0  
            ' ***Identify the first task that completes.  
            Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)  
  
            ' ***Remove the selected task from the list so that you don't  
            ' process it more than once.  
            downloadTasks.Remove(finishedTask)  
  
            ' ***Await the first completed task and display the results.  
            Dim length = Await finishedTask  
            resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website:  {0}" & vbCrLf, length)  
        End While  
  
    End Function  
  
    ' Bundle the processing steps for a website into one async method.  
    Async Function ProcessURLAsync(url As String, client As HttpClient, ct As CancellationToken) As Task(Of Integer)  
  
        ' GetAsync returns a Task(Of HttpResponseMessage).
        Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)  
  
        ' Retrieve the website contents from the HttpResponseMessage.  
        Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()  
  
        Return urlContents.Length  
    End Function  
  
    ' Add a method that creates a list of web addresses.  
    Private Function SetUpURLList() As List(Of String)  
  
        Dim urls = New List(Of String) From  
            {  
                "https://msdn.microsoft.com",  
                "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  
  
End Class  
  
' Sample output:  
  
' Length of the download:  226093  
' Length of the download:  412588  
' Length of the download:  175490  
' Length of the download:  204890  
' Length of the download:  158855  
' Length of the download:  145790  
' Length of the download:  44908  
' Downloads complete.  

Lihat juga