Cancel an Async Task or a List of Tasks (Visual Basic)

You can set up a button that you can use to cancel an async application if you don't want to wait for it to finish. By following the examples in this topic, you can add a cancellation button to an application that downloads the contents of one website or a list of websites.

The examples use the UI that Fine-Tuning Your Async Application (Visual Basic) describes.

Note

To run the examples, you must have Visual Studio 2012 or newer and the .NET Framework 4.5 or newer installed on your computer.

Cancel a Task

The first example associates the Cancel button with a single download task. If you choose the button while the application is downloading content, the download is canceled.

Downloading the Example

You can download the complete Windows Presentation Foundation (WPF) project from Async Sample: Fine Tuning Your Application and then follow these steps.

  1. Decompress the file that you downloaded, and then start Visual Studio.

  2. On the menu bar, choose File, Open, Project/Solution.

  3. In the Open Project dialog box, open the folder that holds the sample code that you decompressed, and then open the solution (.sln) file for AsyncFineTuningVB.

  4. In Solution Explorer, open the shortcut menu for the CancelATask project, and then choose Set as StartUp Project.

  5. Choose the F5 key to run the project.

    Choose the Ctrl+F5 keys to run the project without debugging it.

If you don't want to download the project, you can review the MainWindow.xaml.vb files at the end of this topic.

Building the Example

The following changes add a Cancel button to an application that downloads a website. If you don't want to download or build the example, you can review the final product in the "Complete Examples" section at the end of this topic. Asterisks mark the changes in the code.

To build the example yourself, step by step, follow the instructions in the "Downloading the Example" section, but choose StarterCode as the StartUp Project instead of CancelATask.

Then add the following changes to the MainWindow.xaml.vb file of that project.

  1. Declare a CancellationTokenSource variable, cts, that’s in scope for all methods that access it.

    Class MainWindow
    
        ' ***Declare a System.Threading.CancellationTokenSource.
        Dim cts As CancellationTokenSource
    
  2. Add the following event handler for the Cancel button. The event handler uses the CancellationTokenSource.Cancel method to notify cts when the user requests cancellation.

    ' ***Add an event handler for the Cancel button.
    Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
    
        If cts IsNot Nothing Then
            cts.Cancel()
        End If
    End Sub
    
  3. Make the following changes in the event handler for the Start button, startButton_Click.

    • Instantiate the CancellationTokenSource, cts.

      ' ***Instantiate the CancellationTokenSource.
      cts = New CancellationTokenSource()
      
    • In the call to AccessTheWebAsync, which downloads the contents of a specified website, send the CancellationTokenSource.Token property of cts as an argument. The Token property propagates the message if cancellation is requested. Add a catch block that displays a message if the user chooses to cancel the download operation. The following code shows the changes.

      Try
          ' ***Send a token to carry the message if cancellation is requested.
          Dim contentLength As Integer = Await AccessTheWebAsync(cts.Token)
      
          resultsTextBox.Text &=
              vbCrLf & $"Length of the downloaded string: {contentLength}." & vbCrLf
      
          ' *** If cancellation is requested, an OperationCanceledException results.
      Catch ex As OperationCanceledException
          resultsTextBox.Text &= vbCrLf & "Download canceled." & vbCrLf
      
      Catch ex As Exception
          resultsTextBox.Text &= vbCrLf & "Download failed." & vbCrLf
      End Try
      
  4. In AccessTheWebAsync, use the HttpClient.GetAsync(String, CancellationToken) overload of the GetAsync method in the HttpClient type to download the contents of a website. Pass ct, the CancellationToken parameter of AccessTheWebAsync, as the second argument. The token carries the message if the user chooses the Cancel button.

    The following code shows the changes in AccessTheWebAsync.

    ' ***Provide a parameter for the CancellationToken.
    Async Function AccessTheWebAsync(ct As CancellationToken) As Task(Of Integer)
    
        Dim client As HttpClient = New HttpClient()
    
        resultsTextBox.Text &= vbCrLf & "Ready to download." & vbCrLf
    
        ' You might need to slow things down to have a chance to cancel.
        Await Task.Delay(250)
    
        ' GetAsync returns a Task(Of HttpResponseMessage).
        ' ***The ct argument carries the message if the Cancel button is chosen.
        Dim response As HttpResponseMessage = Await client.GetAsync("https://msdn.microsoft.com/library/dd470362.aspx", ct)
    
        ' Retrieve the website contents from the HttpResponseMessage.
        Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()
    
        ' The result of the method is the length of the downloaded website.
        Return urlContents.Length
    End Function
    
  5. If you don’t cancel the program, it produces the following output:

    Ready to download.
    Length of the downloaded string: 158125.
    

    If you choose the Cancel button before the program finishes downloading the content, the program produces the following output:

    Ready to download.
    Download canceled.
    

Cancel a List of Tasks

You can extend the previous example to cancel many tasks by associating the same CancellationTokenSource instance with each task. If you choose the Cancel button, you cancel all tasks that aren’t yet complete.

Downloading the Example

You can download the complete Windows Presentation Foundation (WPF) project from Async Sample: Fine Tuning Your Application and then follow these steps.

  1. Decompress the file that you downloaded, and then start Visual Studio.

  2. On the menu bar, choose File, Open, Project/Solution.

  3. In the Open Project dialog box, open the folder that holds the sample code that you decompressed, and then open the solution (.sln) file for AsyncFineTuningVB.

  4. In Solution Explorer, open the shortcut menu for the CancelAListOfTasks project, and then choose Set as StartUp Project.

  5. Choose the F5 key to run the project.

    Choose the Ctrl+F5 keys to run the project without debugging it.

If you don't want to download the project, you can review the MainWindow.xaml.vb files at the end of this topic.

Building the Example

To extend the example yourself, step by step, follow the instructions in the "Downloading the Example" section, but choose CancelATask as the StartUp Project. Add the following changes to that project. Asterisks mark the changes in the program.

  1. Add a method to create a list of web addresses.

    ' ***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
    
  2. Call the method in AccessTheWebAsync.

    ' ***Call SetUpURLList to make a list of web addresses.
    Dim urlList As List(Of String) = SetUpURLList()
    
  3. Add the following loop in AccessTheWebAsync to process each web address in the list.

    ' ***Add a loop to process the list of web addresses.
    For Each url In urlList
        ' GetAsync returns a Task(Of HttpResponseMessage).
        ' Argument ct carries the message if the Cancel button is chosen.
        ' ***Note that the Cancel button can cancel all remaining downloads.
        Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)
    
        ' Retrieve the website contents from the HttpResponseMessage.
        Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()
    
        resultsTextBox.Text &=
            vbCrLf & $"Length of the downloaded string: {urlContents.Length}." & vbCrLf
    Next
    
  4. Because AccessTheWebAsync displays the lengths, the method doesn't need to return anything. Remove the return statement, and change the return type of the method to Task instead of Task<TResult>.

    Async Function AccessTheWebAsync(ct As CancellationToken) As Task
    

    Call the method from startButton_Click by using a statement instead of an expression.

    Await AccessTheWebAsync(cts.Token)
    
  5. If you don’t cancel the program, it produces the following output:

    Length of the downloaded string: 35939.
    
    Length of the downloaded string: 237682.
    
    Length of the downloaded string: 128607.
    
    Length of the downloaded string: 158124.
    
    Length of the downloaded string: 204890.
    
    Length of the downloaded string: 175488.
    
    Length of the downloaded string: 145790.
    
    Downloads complete.
    

    If you choose the Cancel button before the downloads are complete, the output contains the lengths of the downloads that completed before the cancellation.

    Length of the downloaded string: 35939.
    
    Length of the downloaded string: 237682.
    
    Length of the downloaded string: 128607.
    
    Downloads canceled.
    

Complete Examples

The following sections contain the code for each of the previous examples. Notice that you must add a reference for System.Net.Http.

You can download the projects from Async Sample: Fine Tuning Your Application.

Cancel a Task Example

The following code is the complete MainWindow.xaml.vb file for the example that cancels a single task.

' 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
            ' ***Send a token to carry the message if cancellation is requested.
            Dim contentLength As Integer = Await AccessTheWebAsync(cts.Token)

            resultsTextBox.Text &=
                vbCrLf & $"Length of the downloaded string: {contentLength}." & vbCrLf

            ' *** If cancellation is requested, an OperationCanceledException results.
        Catch ex As OperationCanceledException
            resultsTextBox.Text &= vbCrLf & "Download canceled." & vbCrLf

        Catch ex As Exception
            resultsTextBox.Text &= vbCrLf & "Download failed." & vbCrLf
        End Try

        ' ***Set the CancellationTokenSource to Nothing when the download is complete.
        cts = Nothing
    End Sub

    ' ***Add an event handler for the Cancel button.
    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.
    Async Function AccessTheWebAsync(ct As CancellationToken) As Task(Of Integer)

        Dim client As HttpClient = New HttpClient()

        resultsTextBox.Text &=
            vbCrLf & "Ready to download." & vbCrLf

        ' You might need to slow things down to have a chance to cancel.
        Await Task.Delay(250)

        ' GetAsync returns a Task(Of HttpResponseMessage).
        ' ***The ct argument carries the message if the Cancel button is chosen.
        Dim response As HttpResponseMessage = Await client.GetAsync("https://msdn.microsoft.com/library/dd470362.aspx", ct)

        ' Retrieve the website contents from the HttpResponseMessage.
        Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()

        ' The result of the method is the length of the downloaded website.
        Return urlContents.Length
    End Function
End Class

' Output for a successful download:

' Ready to download.

' Length of the downloaded string: 158125.

' Or, if you cancel:

' Ready to download.

' Download canceled.

Cancel a List of Tasks Example

The following code is the complete MainWindow.xaml.vb file for the example that cancels a list of tasks.

' 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
            ' ***AccessTheWebAsync returns a Task, not a Task(Of Integer).
            Await AccessTheWebAsync(cts.Token)
            '  ***Small change in the display lines.
            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

    ' Add an event handler for the Cancel button.
    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()

        ' ***Add a loop to process the list of web addresses.
        For Each url In urlList
            ' GetAsync returns a Task(Of HttpResponseMessage).
            ' Argument ct carries the message if the Cancel button is chosen.
            ' ***Note that the Cancel button can cancel all remaining downloads.
            Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)

            ' Retrieve the website contents from the HttpResponseMessage.
            Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()

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

' Output if you do not choose to cancel:

' Length of the downloaded string: 35939.

' Length of the downloaded string: 237682.

' Length of the downloaded string: 128607.

' Length of the downloaded string: 158124.

' Length of the downloaded string: 204890.

' Length of the downloaded string: 175488.

' Length of the downloaded string: 145790.

' Downloads complete.

'  Sample output if you choose to cancel:

' Length of the downloaded string: 35939.

' Length of the downloaded string: 237682.

' Length of the downloaded string: 128607.

' Downloads canceled.

See also