Cancelar tarefas assíncronas após um período (C# e Visual Basic)

Você pode cancelar uma operação assíncrona após um período de tempo usando o método CancellationTokenSource.CancelAfter se não quiser esperar a conclusão da operação. Este método agenda o cancelamento de todas as tarefas associadas que não foram concluídas dentro do período de tempo designado pela expressão CancelAfter.

Este exemplo adiciona o código que é desenvolvido no Cancelar uma tarefa assíncrona ou uma lista de tarefas (C# e Visual Basic) para baixar uma lista de sites e exibir o comprimento do conteúdo de cada um.

Dica

Para executar os exemplos, você deve ter o Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 para Windows Desktop, Visual Studio Express 2013 para Windows, ou o .NET Framework 4.5 ou 4.5.1 instalado em seu computador.

Baixando o Exemplo

Você pode baixar projeto completo do Windows Presentation Foundation (WPF) de Exemplo de Async: Ajustando seu aplicativo.

  1. Descompacte o arquivo que você baixou e inicie o Visual Studio.

  2. Na barra de menu, escolha Arquivo, Abrir, Projeto/solução.

  3. Na caixa de diálogo Abrir Projeto , abra a pasta que contém o código de exemplo que você descompactou, e abra o arquivo de solução (.sln) para AsyncFineTuningCS ou AsyncFineTuningVB.

  4. Em Gerenciador de Soluções, abra o menu de atalho para o projeto CancelAfterTime e escolha Definir como Projeto de Inicialização.

  5. Escolha a tecla F5 para executar o projeto.

    Escolha as chaves Ctrl+F5 para executar o projeto sem depurá-las.

  6. Execute o programa várias vezes para verificar se a saída pode mostrar saída para todos os sites, os sites, ou alguns sites.

Se você não quiser baixar o projeto, você pode examinar os arquivos de MainWindow.xaml.vb e de MainWindow.xaml.cs no final deste tópico.

Compilando o Exemplo

O exemplo neste tópico é adicionado ao projeto que é desenvolvido em Cancelar uma tarefa assíncrona ou uma lista de tarefas (C# e Visual Basic) para cancelar uma lista de tarefas. O exemplo usa a mesma interface do usuário, embora o botão Cancelar não seja usado explicitamente.

Para criar o exemplo você mesmo, passo a passo, siga as instruções na seção "Baixando o exemplo", mas selecione CancelAListOfTasks como Projeto de inicialização. Adicione as alterações neste tópico para o projeto.

Para especificar um horário máximo antes que as tarefas sejam marcadas como canceladas, adicione uma chamada a CancelAfter para startButton_Click, como mostra o exemplo a seguir. A adição é marcada com asteriscos.

Private Async Sub startButton_Click(sender As Object, e As RoutedEventArgs)

    ' Instantiate the CancellationTokenSource.
    cts = New CancellationTokenSource()

    resultsTextBox.Clear()

    Try 
        ' ***Set up the CancellationTokenSource to cancel after 2.5 seconds. (You  
        ' can adjust the time.)
        cts.CancelAfter(2500)

        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
private async void startButton_Click(object sender, RoutedEventArgs e)
{
    // Instantiate the CancellationTokenSource.
    cts = new CancellationTokenSource();

    resultsTextBox.Clear();

    try
    {
        // ***Set up the CancellationTokenSource to cancel after 2.5 seconds. (You 
        // can adjust the time.)
        cts.CancelAfter(2500);

        await AccessTheWebAsync(cts.Token);
        resultsTextBox.Text += "\r\nDownloads succeeded.\r\n";
    }
    catch (OperationCanceledException)
    {
        resultsTextBox.Text += "\r\nDownloads canceled.\r\n";
    }
    catch (Exception)
    {
        resultsTextBox.Text += "\r\nDownloads failed.\r\n";
    }

    cts = null; 
}

Execute o programa várias vezes para verificar se a saída pode mostrar saída para todos os sites, os sites, ou alguns sites. A saída a seguir é um modelo.

Length of the downloaded string: 35990.

Length of the downloaded string: 407399.

Length of the downloaded string: 226091.

Downloads canceled.

Exemplo completo

O código a seguir é o texto completo de MainWindow.xaml.vb ou de MainWindow.xaml.cs do exemplo. Os asteriscos marcam os elementos que foram adicionados para esse exemplo.

Observe que você deve adicionar uma referência para System.Net.Http.

Você pode baixar o projeto de Exemplo de Async: Ajustando seu aplicativo.

' 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 
            ' ***Set up the CancellationTokenSource to cancel after 2.5 seconds. (You  
            ' can adjust the time.)
            cts.CancelAfter(2500)

            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()

        ' Process each element in 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 &=
                String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, urlContents.Length)
        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/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function 

End Class 


' Sample output: 

' Length of the downloaded string: 35990. 

' Length of the downloaded string: 407399. 

' Length of the downloaded string: 226091. 

' Downloads canceled.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// Add a using directive and a reference for System.Net.Http. 
using System.Net.Http;

// Add the following using directive. 
using System.Threading;

namespace CancelAfterTime
{
    public partial class MainWindow : Window
    {
        // Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;

        public MainWindow()
        {
            InitializeComponent();
        }


        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the CancellationTokenSource.
            cts = new CancellationTokenSource();

            resultsTextBox.Clear();

            try
            {
                // ***Set up the CancellationTokenSource to cancel after 2.5 seconds. (You 
                // can adjust the time.)
                cts.CancelAfter(2500);

                await AccessTheWebAsync(cts.Token);
                resultsTextBox.Text += "\r\nDownloads succeeded.\r\n";
            }
            catch (OperationCanceledException)
            {
                resultsTextBox.Text += "\r\nDownloads canceled.\r\n";
            }
            catch (Exception)
            {
                resultsTextBox.Text += "\r\nDownloads failed.\r\n";
            }

            cts = null; 
        }


        // You can still include a Cancel button if you want to. 
        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        }


        async Task AccessTheWebAsync(CancellationToken ct)
        {
            // Declare an HttpClient object.
            HttpClient client = new HttpClient();

            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();

            foreach (var url in urlList)
            {
                // GetAsync returns a Task<HttpResponseMessage>.  
                // Argument ct carries the message if the Cancel button is chosen.  
                // Note that the Cancel button cancels all remaining downloads.
                HttpResponseMessage response = await client.GetAsync(url, ct);

                // Retrieve the website contents from the HttpResponseMessage. 
                byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

                resultsTextBox.Text +=
                    String.Format("\r\nLength of the downloaded string: {0}.\r\n", urlContents.Length);
            }
        }


        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            };
            return urls;
        }
    }

    // Sample Output: 

    // Length of the downloaded string: 35990. 

    // Length of the downloaded string: 407399. 

    // Length of the downloaded string: 226091. 

    // Downloads canceled.
}

Consulte também

Tarefas

Instruções passo a passo: acessando a Web e usando Async e Await (C# e Visual Basic)

Conceitos

Programação assíncrona com Async e Await (C# e Visual Basic)

Cancelar uma tarefa assíncrona ou uma lista de tarefas (C# e Visual Basic)

Ajustando seu aplicativo Async (C# e Visual Basic)

Outros recursos

Exemplo de Async: Ajustando o aplicativo