Отмена асинхронных задач после определенного периода времени (C# и Visual Basic)

Асинхронную операцию можно отменить после определенного периода времени с помощью метода CancellationTokenSource.CancelAfter в случае, если не требуется ожидание завершения операции. Этот метод планирует отмену всех связанных задач, которые не были завершены в течение периода времени, заданного выражением CancelAfter.

Этот пример добавляется к коду, разработанному в разделе Отмена асинхронной задачи или списка задач (C# и Visual Basic), чтобы загрузить список веб-сайтов и отобразить длину содержимого каждого из них.

Примечание

Для запуска примеров необходимо, чтобы на компьютере была установлена Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 для Windows Desktop, Visual Studio Express 2013 для Windows или .NET Framework 4.5 или 4.5.1.

Загрузка примера

Загрузить полный проект Windows Presentation Foundation (WPF) можно с сайта Пример асинхронности. Тонкая настройка приложения, а затем выполнить необходимые действия.

  1. Распакуйте загруженный файл и запустите Visual Studio.

  2. В строке меню выберите Файл, Открыть, Проект/Решение.

  3. В диалоговом окне Открыть проект откройте папку, которая содержит пример кода, который распаковали, а затем откройте файл решения (SLN) для AsyncFineTuningCS или AsyncFineTuningVB.

  4. В Обозревателе решений откройте контекстное меню проекта CancelAfterTime и выберите команду Назначить запускаемым проектом.

  5. Нажмите клавишу F5, чтобы запустить проект.

    Нажмите клавиши Ctrl+F5, чтобы запустить проект без отладки.

  6. Запустите программу несколько раз, чтобы проверить, что в выходных данных могут отображаться данные для всех веб-сайтов, никаких веб-сайтов или некоторых веб-сайтов.

Если не хотите загружать проект, можете просмотреть файлы MainWindow.xaml.vb и MainWindow.xaml.cs в конце этого раздела.

Построение примера

Пример в этом разделе добавляет в проект, который разработан в Отмена асинхронной задачи или списка задач (C# и Visual Basic) для отмены списка задач. В этом примере используется один и тот же пользовательский интерфейс, хотя кнопка Отмена не используется явно.

Для самостоятельной сборки примера шаг за шагом следуйте инструкциям в разделе "Загрузка примера", но выберите CancelAListOfTasks как Запускаемый проект. Добавьте изменения в данном разделе в этот проект.

Чтобы указать максимальную длительность выполнения задачи, прежде чем она будет помечена для отмены, добавьте вызов CancelAfter к startButton_Click, как показано в следующем примере. Изменения помечены звездочками.

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; 
}

Запустите программу несколько раз, чтобы проверить, что в выходных данных могут отображаться данные для всех веб-сайтов, никаких веб-сайтов или некоторых веб-сайтов. Далее приводится пример вывода:

Length of the downloaded string: 35990.

Length of the downloaded string: 407399.

Length of the downloaded string: 226091.

Downloads canceled.

Полный пример

Приведенный ниже код — полный текст файла MainWindow.xaml.vb или MainWindow.xaml.cs для примера. Звездочками помечаются элементы, добавленные для этого примера.

Обратите внимание, что необходимо добавить ссылку для System.Net.Http.

Можно загрузить проект со страницы Пример асинхронности. Тонкая настройка приложения.

' 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.
}

См. также

Задачи

Пошаговое руководство. Получение доступа к Интернету с помощью модификатора Async и оператора Await (C# и Visual Basic)

Основные понятия

Асинхронное программирование с использованием ключевых слов Async и Await (C# и Visual Basic)

Отмена асинхронной задачи или списка задач (C# и Visual Basic)

Настройка асинхронного приложения (C# и Visual Basic)

Другие ресурсы

Пример асинхронности. Тонкая настройка приложения