Cancelar uma tarefa assíncrona ou uma lista de tarefas (Visual Basic)
Você pode configurar um botão que pode ser usado para cancelar um aplicativo assíncrono se não desejar aguardar sua conclusão. Seguindo os exemplos neste tópico, você pode adicionar um botão de cancelamento a um aplicativo que baixa o conteúdo de um site ou uma lista de sites.
Os exemplos usam a interface do usuário que Ajuste fino de seu aplicativo assíncrono (C#) descreve.
Observação
Para executar os exemplos, você precisa ter o Visual Studio 2012 ou uma versão mais recente e o .NET Framework 4.5 ou posterior instalados em seu computador.
Cancelar uma tarefa
O primeiro exemplo associa o botão Cancelar a uma única tarefa de download. Se você escolher o botão enquanto o aplicativo está baixando conteúdo, o download será cancelado.
Baixando o Exemplo
Você pode baixar o projeto completo do WPF (Windows Presentation Foundation) em Exemplo assíncrono: ajuste fino de seu aplicativo e, em seguida, seguir estas etapas.
Descompacte o arquivo baixado e, em seguida, inicie o Visual Studio.
Na barra de menus, escolha Arquivo, Abrir, Projeto/Solução.
Na caixa de diálogo Abrir Projeto, abra a pasta em que está o código de exemplo que você descompactou e, em seguida, abra o arquivo de solução (.sln) de AsyncFineTuningVB.
No Gerenciador de Soluções, abra o menu de atalho do projeto CancelATask e, em seguida, escolha Definir como Projeto de Inicialização.
Escolha a tecla F5 para executar o projeto.
Escolha as teclas CTRL+F5 para executar o projeto sem depurá-lo.
Se não quiser baixar o projeto, você poderá examinar o arquivo MainWindow.xaml.vb no final deste tópico.
Compilando o Exemplo
As alterações a seguir adicionam um botão Cancelar a um aplicativo que baixa um site. Se não desejar baixar ou compilar o exemplo, você poderá examinar o produto final na seção "Exemplos completos" no final deste tópico. Os asteriscos marcam as alterações no código.
Para compilar o exemplo você mesmo, passo a passo, siga as instruções na seção “Baixando o exemplo”, mas escolha StarterCode como o Projeto de Inicialização em vez de CancelATask.
Em seguida, adicione as seguintes alterações ao arquivo MainWindow.xaml.cs desse projeto.
Declare uma variável
CancellationTokenSource
,cts
, que está no escopo para todos os métodos a acessarem.Class MainWindow ' ***Declare a System.Threading.CancellationTokenSource. Dim cts As CancellationTokenSource
Adicione o seguinte manipulador de eventos para o botão Cancelar. O manipulador de eventos usa o método CancellationTokenSource.Cancel para notificar
cts
quando o usuário solicita o cancelamento.' ***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
Faça as seguintes alterações no manipulador de eventos para o botão Iniciar,
startButton_Click
.Crie a instância de
CancellationTokenSource
,cts
.' ***Instantiate the CancellationTokenSource. cts = New CancellationTokenSource()
Na chamada para
AccessTheWebAsync
, que baixa o conteúdo de um site especificado, envie a propriedade CancellationTokenSource.Token dects
como um argumento. A propriedadeToken
propaga a mensagem se o cancelamento é solicitado. Adicione um bloco catch que exibe uma mensagem se o usuário optar por cancelar a operação de download. O código a seguir mostra as alterações.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
No
AccessTheWebAsync
, use a sobrecarga HttpClient.GetAsync(String, CancellationToken) do métodoGetAsync
no tipo HttpClient para baixar o conteúdo de um site. Passect
, o parâmetro CancellationToken deAccessTheWebAsync
, como o segundo argumento. O token executa a mensagem se o usuário escolhe o botão Cancelar.O código a seguir mostra as alterações em
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
Se você não cancelar o programa, ele produzirá a saída a seguir:
Ready to download. Length of the downloaded string: 158125.
Se você escolher o botão Cancelar antes de o programa terminar de baixar o conteúdo, o programa produzirá a saída a seguir:
Ready to download. Download canceled.
Cancelar uma lista de tarefas
Você pode estender o exemplo anterior para cancelar muitas tarefas associando a mesma instância CancellationTokenSource
a cada tarefa. Se você escolher o botão Cancelar, cancela todas as tarefas que ainda não estão concluídas.
Baixando o Exemplo
Você pode baixar o projeto completo do WPF (Windows Presentation Foundation) em Exemplo assíncrono: ajuste fino de seu aplicativo e, em seguida, seguir estas etapas.
Descompacte o arquivo baixado e, em seguida, inicie o Visual Studio.
Na barra de menus, escolha Arquivo, Abrir, Projeto/Solução.
Na caixa de diálogo Abrir Projeto, abra a pasta em que está o código de exemplo que você descompactou e, em seguida, abra o arquivo de solução (.sln) de AsyncFineTuningVB.
No Gerenciador de Soluções, abra o menu de atalho do projeto CancelAListOfTasks e, em seguida, escolha Definir como Projeto de Inicialização.
Escolha a tecla F5 para executar o projeto.
Escolha as teclas CTRL+F5 para executar o projeto sem depurá-lo.
Se não quiser baixar o projeto, você poderá examinar o arquivo MainWindow.xaml.vb no final deste tópico.
Compilando o Exemplo
Para estender o exemplo você mesmo, passo a passo, siga as instruções na seção "Baixando o exemplo", mas escolha CancelATask como o Projeto de Inicialização. Adicione as seguintes alterações ao projeto. Os asteriscos marcam as alterações no programa.
Adicione um método para criar uma lista de endereços Web.
' ***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
Chame o método em
AccessTheWebAsync
.' ***Call SetUpURLList to make a list of web addresses. Dim urlList As List(Of String) = SetUpURLList()
Adicione o seguinte loop em
AccessTheWebAsync
para processar cada endereço web na lista.' ***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
Como
AccessTheWebAsync
exibe os comprimentos, o método não precisa retornar nada. Remova a instrução de retorno e altere o tipo de retorno do método para Task em vez de Task<TResult>.Async Function AccessTheWebAsync(ct As CancellationToken) As Task
Chame o método de
startButton_Click
usando uma instrução em vez de uma expressão.Await AccessTheWebAsync(cts.Token)
Se você não cancelar o programa, ele produzirá a saída a seguir:
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.
Se você escolher o botão Cancelar antes de os downloads serem concluídos, a saída conterá os tamanhos dos downloads que foram concluídos antes do cancelamento.
Length of the downloaded string: 35939. Length of the downloaded string: 237682. Length of the downloaded string: 128607. Downloads canceled.
Exemplos completos
As seções a seguir contêm o código para cada um dos exemplos anteriores. Observe que você deve adicionar uma referência para System.Net.Http.
Você pode baixar os projetos de Exemplo assíncrono: ajuste fino de seu aplicativo.
Exemplo de cancelar uma tarefa
O código a seguir é o arquivo MainWindow.xaml.cs completo do exemplo que cancela uma única tarefa.
' 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.
Exemplo de cancelar uma lista de tarefas
O código a seguir é o arquivo MainWindow.xaml.cs completo do exemplo que cancela uma lista de tarefas.
' 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.