當您在應用程式中包含異步程式代碼時,您應該考慮並可能防止重入性,這指的是在異步操作完成之前重新進入該操作。 如果您未識別並處理重新進入的可能性,可能會導致非預期的結果。
備註
若要執行此範例,您必須在計算機上安裝Visual Studio 2012或更新版本,以及已安裝 .NET Framework 4.5 或更新版本。
備註
傳輸層安全性 (TLS) 1.2 版現在是應用程式開發中使用的最低版本。 如果您的應用程式以 4.7 之前的 .NET Framework 版本為目標,請參閱下列文章,瞭解 .NET Framework 的傳輸層安全性(TLS) 最佳做法。
識別重新進入
在本主題的範例中,用戶選擇 [ 開始 ] 按鈕來起始異步應用程式,以下載一系列網站,並計算所下載的位元組總數。 在此範例的同步版本中,無論使用者點擊按鈕多少次,在第一次點擊之後,因為應用程式正在執行,所以 UI 執行緒會忽略這些事件。 不過,在異步應用程式中,UI 線程會繼續回應,而且您可能會在完成之前重新進入異步操作。
如果使用者只選擇 [ 開始 ] 按鈕一次,下列範例會顯示預期的輸出。 下載的網站清單會顯示每個網站的大小,以位元組為單位。 位元組總數會出現在結尾。
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 重新啟用按鈕,讓使用者可以再次執行應用程式。
下列程式代碼顯示這些變更,這些變更會以星號標示。 您可以在本主題結尾將變更新增至程式碼,也可以從 異步樣本:.NET 桌面應用程式中的重新進入性下載已完成的應用程式。 專案名稱為 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)。
若要設定此案例,請對 檢閱和執行範例應用程式中提供的基本程式代碼進行下列變更。 您也可以從 異步範例:.NET 桌面應用程式中的重新進入中下載已完成的應用程式。 此專案的名稱為 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 完成之前啟動,但每個群組的輸出會個別顯示。 群組 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)
變數TaskpendingWork會監督顯示程式,並防止任何群組中斷另一個群組的顯示作業。 字元變數 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 以控制顯示程式。 方法會使用 Language Integrated Query(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第一個啟動的群組 A 的
pendingWork工作只在Nothing的開始由FinishOneGroupAsync執行。 群組 A 尚未在到達FinishOneGroupAsync時完成 await 運算式。 因此,控件尚未傳回至AccessTheWebAsync,且對pendingWork的第一個指派尚未發生。下列兩行一律會出現在輸出中。 在 中
StartButton_Click啟動群組的作業,以及將群組的工作指派給pendingWork之間,程式代碼永遠不會中斷。#Starting group B. #Task assigned for group B. Download tasks are active.在群組輸入
StartButton_Click之後,作業不會完成 await 運算式,直到作業進入FinishOneGroupAsync為止。 因此,在該程式代碼區段期間,沒有其他作業可以取得控制權。
檢閱和執行範例應用程式
若要進一步瞭解範例應用程式,您可以自行下載、自行建置,或在本主題結尾檢閱程序代碼,而不實作應用程式。
備註
若要以 Windows Presentation Foundation(WPF) 傳統型應用程式的形式執行此範例,您必須在電腦上安裝 Visual Studio 2012 或更新版本,以及已安裝 .NET Framework 4.5 或更新版本。
下載應用程式
解壓縮您下載的檔案,然後啟動 Visual Studio。
在功能表欄上,選擇 [ 檔案]、[ 開啟]、[ 專案/方案]。
流覽至保存解壓縮範例程式代碼的資料夾,然後開啟方案 (.sln) 檔案。
在 [方案總管] 中,開啟您要執行之專案的快捷方式功能表,然後選擇 [ 設定為 StartUpProject]。
選擇 CTRL+F5 鍵來建置並執行專案。
建置應用程式
下一節提供程式碼,以 WPF 應用程式的形式建置範例。
建置 WPF 應用程式
啟動 Visual Studio。
在功能表欄上,選擇 [ 檔案]、[ 新增]、[ 專案]。
[ 新增專案 ] 對話框隨即開啟。
在 [ 已安裝的範本 ] 窗格中,展開 [Visual Basic],然後展開 [Windows]。
在專案類型清單中,選擇 [WPF 應用程式]。
將專案
WebsiteDownloadWPF命名為 ,選擇 4.6 或更高版本的 .NET Framework 版本,然後按兩下 [ 確定] 按鈕。新的專案會出現在 [方案總管] 中。
在 Visual Studio Code 編輯器中,選擇 MainWindow.xaml 索引標籤 。
如果看不到索引標籤,請在 [方案總管] 中開啟 MainWindow.xaml 的快捷方式選單,然後選擇 [檢視程式碼]。
在MainWindow.xaml的 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 鍵以執行程式,然後選擇 [ 開始 ] 按鈕數次。
從 停用開始按鈕、取消並重新啟動操作,或者 執行多個操作並將輸出排入佇列,以處理重入性。