Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
При включении асинхронного кода в приложение следует рассмотреть и, возможно, предотвратить повторение, которое относится к повторному вводу асинхронной операции перед его завершением. Если вы не определяете и обрабатываете возможности повторного входа, это может привести к непредвиденным результатам.
Замечание
Чтобы запустить пример, необходимо установить Visual Studio 2012 или более поздней версии и .NET Framework 4.5 или более поздней версии на компьютере.
Замечание
Протокол TLS версии 1.2 теперь является минимальной версией, используемой в разработке приложений. Если приложение предназначено для версии .NET Framework более ранней версии 4.7, ознакомьтесь со следующей статьей по рекомендациям по протоколу TLS с помощью .NET Framework.
Распознавание повторного входа
В примере в этом разделе пользователи выбирают кнопку "Пуск ", чтобы инициировать асинхронное приложение, которое скачивает ряд веб-сайтов и вычисляет общее количество скачанных байтов. Синхронная версия примера будет отвечать одинаково независимо от того, сколько раз пользователь выбирает кнопку, так как после первого раза поток пользовательского интерфейса игнорирует эти события, пока приложение не завершит работу. Однако в асинхронном приложении поток пользовательского интерфейса продолжает реагировать, и вы можете повторно ввести асинхронную операцию до завершения.
В следующем примере показаны ожидаемые выходные данные, если пользователь нажимает кнопку "Пуск " только один раз. Список загруженных веб-сайтов отображается с размером в байтах каждого сайта. Общее число байтов отображается в конце.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
Однако если пользователь выбирает кнопку несколько раз, обработчик событий вызывается повторно, а процесс скачивания снова вводится каждый раз. В результате одновременно выполняются несколько асинхронных операций, выходные данные пересекают результаты, а общее количество байтов запутано.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
6. msdn.microsoft.com/library/ms404677.aspx 197325
3. msdn.microsoft.com/library/jj155761.aspx 29019
7. msdn.microsoft.com 42972
4. msdn.microsoft.com/library/hh290140.aspx 117152
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
5. msdn.microsoft.com/library/hh524395.aspx 68959
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
6. msdn.microsoft.com/library/ms404677.aspx 197325
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
7. msdn.microsoft.com 42972
5. msdn.microsoft.com/library/hh524395.aspx 68959
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
Вы можете просмотреть код, который создает эти выходные данные, прокрутив до конца этого раздела. Вы можете поэкспериментировать с кодом, скачав решение на локальный компьютер, а затем запустив проект WebsiteDownload или с помощью кода в конце этого раздела, чтобы создать собственный проект. Дополнительные сведения и инструкции см. в разделе "Просмотр и запуск примера приложения".
Обработка повторного входа
Можно обрабатывать повторный вход различными способами в зависимости от того, что вы хотите, чтобы ваше приложение делало. В этом разделе приведены следующие примеры:
-
Отключите кнопку "Пуск " во время выполнения операции, чтобы пользователь не смог прервать его.
-
Отмените любую операцию, которая по-прежнему выполняется, когда пользователь снова нажимает кнопку "Пуск ", а затем позволить последней запрошенной операции продолжить.
Запустите несколько операций и поставьте результат в очередь
Разрешить асинхронному выполнению всех запрошенных операций, но координировать отображение выходных данных таким образом, чтобы результаты каждой операции отображались вместе и в порядке.
Отключение кнопки "Пуск"
Вы можете заблокировать кнопку "Пуск " во время выполнения операции, отключив кнопку в верхней части обработчика StartButton_Click
событий. После завершения операции можно повторно включить кнопку из Finally
блока, чтобы пользователи могли снова запустить приложение.
В следующем коде показаны эти изменения, помеченные звездочками. Вы можете добавить изменения в код в конце этого раздела или скачать готовое приложение из Async Samples: Reentrancy in .NET Desktop Apps. Имя проекта — DisableStartButton.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' This line is commented out to make the results clearer in the output.
'ResultsTextBox.Text = ""
' ***Disable the Start button until the downloads are complete.
StartButton.IsEnabled = False
Try
Await AccessTheWebAsync()
Catch ex As Exception
ResultsTextBox.Text &= vbCrLf & "Downloads failed."
' ***Enable the Start button in case you want to run the program again.
Finally
StartButton.IsEnabled = True
End Try
End Sub
В результате изменений кнопка не отвечает во время AccessTheWebAsync
загрузки веб-сайтов, поэтому процесс невозможно повторно запустить.
Отмена и перезапуск операции
Вместо отключения кнопки "Пуск " можно сохранить активную кнопку, но если пользователь снова выберет эту кнопку, отмените операцию, которая уже запущена и позволить последней запущенной операции продолжить.
Дополнительные сведения об отмене см. в разделе Fine-Tuning Асинхронное приложение (Visual Basic).
Чтобы настроить этот сценарий, внесите следующие изменения в базовый код, предоставленный в разделе "Просмотр и запуск примера приложения". Вы также можете скачать готовое приложение из Async Samples: Reentrancy in .NET Desktop Apps. Имя этого проекта — CancelAndRestart.
Объявите CancellationTokenSource переменную,
cts
, которая находится в области видимости для всех методов.Class MainWindow // Or Class MainPage ' *** Declare a System.Threading.CancellationTokenSource. Dim cts As CancellationTokenSource
В
StartButton_Click
определите, выполняется ли уже операция. Если значениеcts
равноNothing
, операция не активна. Если это значение неNothing
так, операция, которая уже запущена, отменена.' *** If a download process is already underway, cancel it. If cts IsNot Nothing Then cts.Cancel() End If
Задайте
cts
для другого значения, представляющего текущий процесс.' *** Now set cts to cancel the current process if the button is chosen again. Dim newCTS As CancellationTokenSource = New CancellationTokenSource() cts = newCTS
В конце
StartButton_Click
текущий процесс завершается, поэтому установите значениеcts
обратно наNothing
.' *** When the process completes, signal that another process can proceed. If cts Is newCTS Then cts = Nothing End If
В следующем коде показаны все изменения в StartButton_Click
. Дополнения помечаются звездочками.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' This line is commented out to make the results clearer.
'ResultsTextBox.Text = ""
' *** If a download process is underway, cancel it.
If cts IsNot Nothing Then
cts.Cancel()
End If
' *** Now set cts to cancel the current process if the button is chosen again.
Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
cts = newCTS
Try
' *** Send a token to carry the message if the operation is canceled.
Await AccessTheWebAsync(cts.Token)
Catch ex As OperationCanceledException
ResultsTextBox.Text &= vbCrLf & "Download canceled." & vbCrLf
Catch ex As Exception
ResultsTextBox.Text &= vbCrLf & "Downloads failed."
End Try
' *** When the process is complete, signal that another process can proceed.
If cts Is newCTS Then
cts = Nothing
End If
End Sub
В AccessTheWebAsync
внесите следующие изменения.
Добавьте параметр для принятия токена отмены из
StartButton_Click
.Используйте метод GetAsync для скачивания веб-сайтов, поскольку
GetAsync
принимает аргумент CancellationToken.Перед вызовом
DisplayResults
для отображения результатов для каждого скаченного веб-сайта проверьтеct
, чтобы убедиться, что текущая операция не была отменена.
В следующем коде показаны эти изменения, помеченные звездочками.
' *** Provide a parameter for the CancellationToken from StartButton_Click.
Private Async Function AccessTheWebAsync(ct As CancellationToken) As Task
' Declare an HttpClient object.
Dim client = New HttpClient()
' Make a list of web addresses.
Dim urlList As List(Of String) = SetUpURLList()
Dim total = 0
Dim position = 0
For Each url In urlList
' *** Use the HttpClient.GetAsync method because it accepts a
' cancellation token.
Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)
' *** Retrieve the website contents from the HttpResponseMessage.
Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()
' *** Check for cancellations before displaying information about the
' latest site.
ct.ThrowIfCancellationRequested()
position += 1
DisplayResults(url, urlContents, position)
' Update the total.
total += urlContents.Length
Next
' Display the total count for all of the websites.
ResultsTextBox.Text &=
String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned: " & total & vbCrLf)
End Function
При нажатии кнопки "Пуск " несколько раз во время работы этого приложения результаты должны быть похожи на следующие выходные данные:
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 122505
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
Download canceled.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
Download canceled.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
Чтобы исключить частичные списки, раскомментируйте первую строку кода в StartButton_Click
, чтобы очистить текстовое поле каждый раз, когда пользователь перезапускает операцию.
Выполнение нескольких операций и очередь выходных данных
Этот третий пример является самым сложным в том, что приложение запускает другую асинхронную операцию каждый раз, когда пользователь нажимает кнопку "Пуск " и все операции выполняются до завершения. Все запрошенные операции загружают веб-сайты из списка асинхронно, но выходные данные из операций представлены последовательно. То есть фактическое действие скачивания переключается, как показано в выходных данных в разделе "Распознавание повторного входа", но список результатов для каждой группы представлен отдельно.
Операции совместно используют глобальный Taskобъект, pendingWork
который служит контролёром для процесса отображения.
Этот пример можно запустить, вставив изменения в код в сборке приложения, или следуйте инструкциям в разделе "Скачивание приложения ", чтобы скачать пример, а затем запустить проект QueueResults.
В следующих выходных данных отображается результат, если пользователь нажимает кнопку "Пуск " только один раз. Метка буквы A указывает, что результат будет получен при первом выборе кнопки "Пуск ". Числа показывают порядок URL-адресов в списке целевых объектов загрузки.
#Starting group A.
#Task assigned for group A.
A-1. msdn.microsoft.com/library/hh191443.aspx 87389
A-2. msdn.microsoft.com/library/aa578028.aspx 209858
A-3. msdn.microsoft.com/library/jj155761.aspx 30870
A-4. msdn.microsoft.com/library/hh290140.aspx 119027
A-5. msdn.microsoft.com/library/hh524395.aspx 71260
A-6. msdn.microsoft.com/library/ms404677.aspx 199186
A-7. msdn.microsoft.com 53266
A-8. msdn.microsoft.com/library/ff730837.aspx 148020
TOTAL bytes returned: 918876
#Group A is complete.
Если пользователь нажимает кнопку "Пуск " три раза, приложение создает выходные данные, похожие на следующие строки. Строки информации, начинающиеся с знака фунта (#) трассировки хода выполнения приложения.
#Starting group A.
#Task assigned for group A.
A-1. msdn.microsoft.com/library/hh191443.aspx 87389
A-2. msdn.microsoft.com/library/aa578028.aspx 207089
A-3. msdn.microsoft.com/library/jj155761.aspx 30870
A-4. msdn.microsoft.com/library/hh290140.aspx 119027
A-5. msdn.microsoft.com/library/hh524395.aspx 71259
A-6. msdn.microsoft.com/library/ms404677.aspx 199185
#Starting group B.
#Task assigned for group B.
A-7. msdn.microsoft.com 53266
#Starting group C.
#Task assigned for group C.
A-8. msdn.microsoft.com/library/ff730837.aspx 148010
TOTAL bytes returned: 916095
B-1. msdn.microsoft.com/library/hh191443.aspx 87389
B-2. msdn.microsoft.com/library/aa578028.aspx 207089
B-3. msdn.microsoft.com/library/jj155761.aspx 30870
B-4. msdn.microsoft.com/library/hh290140.aspx 119027
B-5. msdn.microsoft.com/library/hh524395.aspx 71260
B-6. msdn.microsoft.com/library/ms404677.aspx 199186
#Group A is complete.
B-7. msdn.microsoft.com 53266
B-8. msdn.microsoft.com/library/ff730837.aspx 148010
TOTAL bytes returned: 916097
C-1. msdn.microsoft.com/library/hh191443.aspx 87389
C-2. msdn.microsoft.com/library/aa578028.aspx 207089
#Group B is complete.
C-3. msdn.microsoft.com/library/jj155761.aspx 30870
C-4. msdn.microsoft.com/library/hh290140.aspx 119027
C-5. msdn.microsoft.com/library/hh524395.aspx 72765
C-6. msdn.microsoft.com/library/ms404677.aspx 199186
C-7. msdn.microsoft.com 56190
C-8. msdn.microsoft.com/library/ff730837.aspx 148010
TOTAL bytes returned: 920526
#Group C is complete.
Группы B и C начинаются до завершения группы А, но выходные данные для каждой группы отображаются отдельно. Сначала отображается все выходные данные группы A, а затем все выходные данные для группы B, а затем все выходные данные для группы C. Приложение всегда отображает группы по порядку и для каждой группы всегда отображает сведения о отдельных веб-сайтах в том порядке, в котором URL-адреса отображаются в списке URL-адресов.
Однако вы не можете предсказать порядок, в котором на самом деле происходят скачивание. После запуска нескольких групп задачи загрузки, создаваемые ими, являются активными. Вы не можете предусмотреть, что A-1 будет загружен перед B-1, и что A-1 будет загружен перед A-2.
Глобальные определения
Пример кода содержит следующие два глобальных объявления, видимые из всех методов.
Class MainWindow ' Class MainPage in Windows Store app.
' ***Declare the following variables where all methods can access them.
Private pendingWork As Task = Nothing
Private group As Char = ChrW(AscW("A") - 1)
Переменная Task
, pendingWork
, контролирует процесс отображения и предотвращает прерывание одной группой операции отображения другой группы. Переменная символов group
обозначает выходные данные из разных групп, чтобы убедиться, что результаты отображаются в ожидаемом порядке.
Обработчик событий click
Обработчик событий StartButton_Click
увеличивает букву группы при каждом нажатии кнопки "Пуск ". Затем обработчик вызывает AccessTheWebAsync
для выполнения операции скачивания.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' ***Verify that each group's results are displayed together, and that
' the groups display in order, by marking each group with a letter.
group = ChrW(AscW(group) + 1)
ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Starting group {0}.", group)
Try
' *** Pass the group value to AccessTheWebAsync.
Dim finishedGroup As Char = Await AccessTheWebAsync(group)
' The following line verifies a successful return from the download and
' display procedures.
ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Group {0} is complete." & vbCrLf, finishedGroup)
Catch ex As Exception
ResultsTextBox.Text &= vbCrLf & "Downloads failed."
End Try
End Sub
Метод AccessTheWebAsync
Этот пример разбивает AccessTheWebAsync
на два метода. Первый метод, AccessTheWebAsync
запускает все задачи загрузки для группы и настраивает pendingWork
для управления процессом отображения. В методе используется языковой интегрированный запрос (запрос LINQ) и ToArray для запуска всех задач загрузки одновременно.
AccessTheWebAsync
затем вызывает FinishOneGroupAsync
, чтобы дождаться завершения каждой загрузки и отобразить её длину.
FinishOneGroupAsync
возвращает задачу, назначенную pendingWork
в AccessTheWebAsync
. Это значение предотвращает прерывание другой операции до завершения задачи.
Private Async Function AccessTheWebAsync(grp As Char) As Task(Of Char)
Dim client = New HttpClient()
' Make a list of the web addresses to download.
Dim urlList As List(Of String) = SetUpURLList()
' ***Kick off the downloads. The application of ToArray activates all the download tasks.
Dim getContentTasks As Task(Of Byte())() =
urlList.Select(Function(addr) client.GetByteArrayAsync(addr)).ToArray()
' ***Call the method that awaits the downloads and displays the results.
' Assign the Task that FinishOneGroupAsync returns to the gatekeeper task, pendingWork.
pendingWork = FinishOneGroupAsync(urlList, getContentTasks, grp)
ResultsTextBox.Text &=
String.Format(vbCrLf & "#Task assigned for group {0}. Download tasks are active." & vbCrLf, grp)
' ***This task is complete when a group has finished downloading and displaying.
Await pendingWork
' You can do other work here or just return.
Return grp
End Function
Метод FinishOneGroupAsync
Этот метод перебирает задачи скачивания в группе, ожидая завершения каждой из них, отображая размер загруженного веб-сайта и добавляя этот размер к общему.
Первая инструкция в FinishOneGroupAsync
использует pendingWork
, чтобы убедиться, что вход в метод не мешает операции, которая уже находится в процессе отображения или ожидает. Если такая операция выполняется, входная операция должна ждать свою очередь.
Private Async Function FinishOneGroupAsync(urls As List(Of String), contentTasks As Task(Of Byte())(), grp As Char) As Task
' Wait for the previous group to finish displaying results.
If pendingWork IsNot Nothing Then
Await pendingWork
End If
Dim total = 0
' contentTasks is the array of Tasks that was created in AccessTheWebAsync.
For i As Integer = 0 To contentTasks.Length - 1
' Await the download of a particular URL, and then display the URL and
' its length.
Dim content As Byte() = Await contentTasks(i)
DisplayResults(urls(i), content, i, grp)
total += content.Length
Next
' Display the total count for all of the websites.
ResultsTextBox.Text &=
String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned: " & total & vbCrLf)
End Function
Этот пример можно выполнить, вставив изменения в код в сборке приложения, или следуйте инструкциям в разделе "Скачивание приложения ", чтобы скачать пример, а затем запустить проект QueueResults.
Точки интереса
Строки информации, начинающиеся с знака фунта (#) в выходных данных, поясняют, как работает этот пример.
В выходных данных показаны следующие шаблоны.
Группу можно запустить, пока предыдущая группа отображает ее выходные данные, но отображение выходных данных предыдущей группы не прерывается.
#Starting group A. #Task assigned for group A. Download tasks are active. A-1. msdn.microsoft.com/library/hh191443.aspx 87389 A-2. msdn.microsoft.com/library/aa578028.aspx 207089 A-3. msdn.microsoft.com/library/jj155761.aspx 30870 A-4. msdn.microsoft.com/library/hh290140.aspx 119037 A-5. msdn.microsoft.com/library/hh524395.aspx 71260 #Starting group B. #Task assigned for group B. Download tasks are active. A-6. msdn.microsoft.com/library/ms404677.aspx 199186 A-7. msdn.microsoft.com 53078 A-8. msdn.microsoft.com/library/ff730837.aspx 148010 TOTAL bytes returned: 915919 B-1. msdn.microsoft.com/library/hh191443.aspx 87388 B-2. msdn.microsoft.com/library/aa578028.aspx 207089 B-3. msdn.microsoft.com/library/jj155761.aspx 30870 #Group A is complete. B-4. msdn.microsoft.com/library/hh290140.aspx 119027 B-5. msdn.microsoft.com/library/hh524395.aspx 71260 B-6. msdn.microsoft.com/library/ms404677.aspx 199186 B-7. msdn.microsoft.com 53078 B-8. msdn.microsoft.com/library/ff730837.aspx 148010 TOTAL bytes returned: 915908
Задача
pendingWork
предназначенаNothing
только в началеFinishOneGroupAsync
для группы А, начавшей первой. Группа A еще не завершила выражение ожидания при достиженииFinishOneGroupAsync
. Поэтому управление не вернулось кAccessTheWebAsync
, и первое присвоениеpendingWork
не произошло.Следующие две строки всегда отображаются вместе в выходных данных. Код никогда не прерывается между запуском операции группы в
StartButton_Click
и назначением задачи этой группе вpendingWork
.#Starting group B. #Task assigned for group B. Download tasks are active.
После того как группа войдёт в
StartButton_Click
, операция не завершает выражение ожидания до тех пор, пока операция не войдёт вFinishOneGroupAsync
. Поэтому никакие другие операции не могут контролировать этот сегмент кода.
Просмотр и запуск примера приложения
Чтобы лучше понять пример приложения, вы можете скачать его, создать его самостоятельно или просмотреть код в конце этого раздела без реализации приложения.
Замечание
Чтобы запустить пример в классическом приложении Windows Presentation Foundation (WPF), необходимо установить Visual Studio 2012 или более поздней версии и .NET Framework 4.5 или более поздней версии на компьютере.
Скачивание приложения
Скачайте сжатый файл из Async Samples: Реентерабельность в классических приложениях .NET.
Распакуйте скачанный файл и запустите Visual Studio.
В строке меню выберите "Файл", "Открыть", "Проект или решение".
Перейдите в папку, содержащую декомжатый пример кода, а затем откройте файл решения (.sln).
В обозревателе решений откройте контекстное меню для проекта, который требуется запустить, а затем выберите "Задать как StartUpProject".
Выберите клавиши CTRL+F5 для сборки и запуска проекта.
Создание приложения
В следующем разделе приведен код для создания примера в виде приложения WPF.
Создание приложения WPF
Запустите Visual Studio.
В строке меню выберите "Файл", "Создать", "Проект".
Откроется диалоговое окно "Новый проект ".
В области установленных шаблонов разверните Visual Basic и разверните Windows.
В списке типов проектов выберите приложение WPF.
Присвойте проекту
WebsiteDownloadWPF
имя, выберите версию .NET Framework версии 4.6 или более поздней, а затем нажмите кнопку "ОК ".Новый проект появится в обозревателе решений.
В редакторе Visual Studio Code выберите вкладку MainWindow.xaml .
Если вкладка не отображается, откройте контекстное меню mainWindow.xaml в обозревателе решений и выберите команду View Code.
В представлении XAML MainWindow.xaml замените код следующим кодом.
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WebsiteDownloadWPF" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Width="517" Height="360"> <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="-1,0,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="53" Background="#FFA89B9B" FontSize="36" Width="518" /> <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="-1,53,0,-36" TextWrapping="Wrap" VerticalAlignment="Top" Height="343" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="518" FontFamily="Lucida Console" /> </Grid> </Window>
Простое окно, содержащее текстовое поле и кнопку, отображается в представлении дизайна MainWindow.xaml.
В обозревателе решений щелкните правой кнопкой мыши ссылки и выберите "Добавить ссылку".
Добавьте ссылку для System.Net.Http, если она еще не выбрана.
В обозревателе решений откройте контекстное меню для MainWindow.xaml.vb и выберите команду "Просмотреть код".
В MainWindow.xaml.vb замените код следующим кодом.
' Add the following Imports statements, and add a reference for System.Net.Http. Imports System.Net.Http Imports System.Threading Class MainWindow Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol Or System.Net.SecurityProtocolType.Tls12 ' This line is commented out to make the results clearer in the output. 'ResultsTextBox.Text = "" Try Await AccessTheWebAsync() Catch ex As Exception ResultsTextBox.Text &= vbCrLf & "Downloads failed." End Try End Sub Private Async Function AccessTheWebAsync() As Task ' Declare an HttpClient object. Dim client = New HttpClient() ' Make a list of web addresses. Dim urlList As List(Of String) = SetUpURLList() Dim total = 0 Dim position = 0 For Each url In urlList ' GetByteArrayAsync returns a task. At completion, the task ' produces a byte array. Dim urlContents As Byte() = Await client.GetByteArrayAsync(url) position += 1 DisplayResults(url, urlContents, position) ' Update the total. total += urlContents.Length Next ' Display the total count for all of the websites. ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned: " & total & vbCrLf) End Function Private Function SetUpURLList() As List(Of String) Dim urls = New List(Of String) From { "https://msdn.microsoft.com/library/hh191443.aspx", "https://msdn.microsoft.com/library/aa578028.aspx", "https://msdn.microsoft.com/library/jj155761.aspx", "https://msdn.microsoft.com/library/hh290140.aspx", "https://msdn.microsoft.com/library/hh524395.aspx", "https://msdn.microsoft.com/library/ms404677.aspx", "https://msdn.microsoft.com", "https://msdn.microsoft.com/library/ff730837.aspx" } Return urls End Function Private Sub DisplayResults(url As String, content As Byte(), pos As Integer) ' Display the length of each website. The string format is designed ' to be used with a monospaced font, such as Lucida Console or ' Global Monospace. ' Strip off the "http:'". Dim displayURL = url.Replace("https://", "") ' Display position in the URL list, the URL, and the number of bytes. ResultsTextBox.Text &= String.Format(vbCrLf & "{0}. {1,-58} {2,8}", pos, displayURL, content.Length) End Sub End Class
Нажмите клавиши CTRL+F5 для запуска программы, а затем нажмите кнопку "Пуск " несколько раз.
Внесите изменения в надписи «Отключить кнопку "Пуск"», «Отмена и перезапуск операции» или «Выполнить несколько операций и постановка заданий в очередь», чтобы реализовать повторный вход.