チュートリアル: Async と Await を使用した Web へのアクセス (Visual Basic)Walkthrough: Accessing the Web by Using Async and Await (Visual Basic)
async/await 機能を使用することで、非同期プログラムをより簡単かつ直感的に記述できます。You can write asynchronous programs more easily and intuitively by using async/await features. 同期コードに似た非同期コードを記述し、通常の非同期コードが必要とする難しいコールバック関数や継続の処理をコンパイラに任せます。You can write asynchronous code that looks like synchronous code and let the compiler handle the difficult callback functions and continuations that asynchronous code usually entails.
非同期機能の詳細については、「Async および Await を使用した非同期プログラミング (Visual Basic)」を参照してください。For more information about the Async feature, see Asynchronous Programming with Async and Await (Visual Basic).
このチュートリアルは、Web サイトの一覧でのバイト数の合計を計算する同期 Windows Presentation Foundation (WPF) アプリケーションから開始します。This walkthrough starts with a synchronous Windows Presentation Foundation (WPF) application that sums the number of bytes in a list of websites. その後、新しい機能を使用して、アプリケーションを非同期ソリューションに変換します。The walkthrough then converts the application to an asynchronous solution by using the new features.
自分でアプリケーションを作成しない場合は、開発者コード サンプルのページから、"非同期サンプル: Web へのアクセスのチュートリアル (C# および Visual Basic)" をダウンロードできます。If you don't want to build the applications yourself, you can download "Async Sample: Accessing the Web Walkthrough (C# and Visual Basic)" from Developer Code Samples.
このチュートリアルでは、次のタスクを行います。In this walkthrough, you complete the following tasks:
- WPF アプリケーションを作成するCreate a WPF application
- 単純な WPF MainWindow をデザインするDesign a simple WPF MainWindow
- 参照を追加するAdd a reference
- 必要な Imports ステートメントを追加するAdd necessary Imports statements
- 同期アプリケーションを作成するCreate a synchronous application
- 同期ソリューションをテストするTest the synchronous solution
- GetURLContents を非同期メソッドに変換するConvert GetURLContents to an asynchronous method
- SumPageSizes を非同期メソッドに変換するConvert SumPageSizes to an asynchronous method
- startButton_Click を非同期メソッドに変換するConvert startButton_Click to an asynchronous method
- 非同期ソリューションをテストするTest the asynchronous solution
- GetURLContentsAsync メソッドを .NET Framework メソッドに置き換えるReplace the GetURLContentsAsync method with a .NET Framework method
非同期のコード例全体については、「例」セクションを参照してください。See the Example section for the complete asynchronous example.
必須コンポーネントPrerequisites
お使いのコンピューターに、Visual Studio 2012 以降がインストールされている必要があります。Visual Studio 2012 or later must be installed on your computer. 詳細については、Visual Studio のダウンロード ページを参照してください。For more information, see the Visual Studio Downloads page.
WPF アプリケーションを作成するCreate a WPF application
Visual Studio を起動します。Start Visual Studio.
メニュー バーで、 [ファイル] 、 [新規作成] 、 [プロジェクト] の順にクリックします。On the menu bar, choose File, New, Project.
[新しいプロジェクト] ダイアログ ボックスが表示されます。The New Project dialog box opens.
[インストールされたテンプレート] ペインで、[Visual Basic] を選択し、プロジェクトの種類の一覧で [WPF アプリケーション] を選択します。In the Installed Templates pane, choose Visual Basic, and then choose WPF Application from the list of project types.
[名前] ボックスに「
AsyncExampleWPF
」と入力して、 [OK] を選択します。In the Name text box, enterAsyncExampleWPF
, and then choose the OK button.ソリューション エクスプローラーに新しいプロジェクトが表示されます。The new project appears in Solution Explorer.
単純な WPF MainWindow をデザインするDesign a simple WPF MainWindow
Visual Studio コード エディターで、 [MainWindow.xaml] タブをクリックします。In the Visual Studio Code Editor, choose the MainWindow.xaml tab.
[ツールボックス] ウィンドウが表示されていない場合は、 [表示] メニューを開き、 [ツールボックス] をクリックします。If the Toolbox window isn’t visible, open the View menu, and then choose Toolbox.
[Button] コントロールと [TextBox] コントロールを [MainWindow] ウィンドウに追加します。Add a Button control and a TextBox control to the MainWindow window.
[TextBox] コントロールを強調表示し、 [プロパティ] ウィンドウで次の値を設定します。Highlight the TextBox control and, in the Properties window, set the following values:
[Name] プロパティを
resultsTextBox
に設定します。Set the Name property toresultsTextBox
.[Height] プロパティを 250 に設定します。Set the Height property to 250.
[Width] プロパティを 500 に設定します。Set the Width property to 500.
[テキスト] タブで、Lucida Console や Global Monospace などの等幅フォントを指定します。On the Text tab, specify a monospaced font, such as Lucida Console or Global Monospace.
[Button] コントロールを強調表示し、 [プロパティ] ウィンドウで次の値を設定します。Highlight the Button control and, in the Properties window, set the following values:
[Name] プロパティを
startButton
に設定します。Set the Name property tostartButton
.[Content] プロパティの値を [Button] から [Start] に変更します。Change the value of the Content property from Button to Start.
テキスト ボックスとボタンの位置を調整し、両方が [MainWindow] ウィンドウ内に表示されるようにします。Position the text box and the button so that both appear in the MainWindow window.
WPF XAML デザイナーについて詳しくは、「XAML デザイナーを使用した UI の作成」をご覧ください。For more information about the WPF XAML Designer, see Creating a UI by using XAML Designer.
参照を追加するAdd a reference
ソリューション エクスプローラーで、プロジェクトの名前を強調表示します。In Solution Explorer, highlight your project's name.
メニュー バーで、 [プロジェクト] 、 [参照の追加] の順に選択します。On the menu bar, choose Project, Add Reference.
[参照マネージャー] ダイアログ ボックスが表示されます。The Reference Manager dialog box appears.
ダイアログ ボックスの上部で、プロジェクトのターゲットが .NET Framework 4.5 以上であることを確認します。At the top of the dialog box, verify that your project is targeting the .NET Framework 4.5 or higher.
[アセンブリ] で、 [フレームワーク] を選択します (選択されていない場合)。In the Assemblies area, choose Framework if it isn’t already chosen.
名前の一覧で、 [System.Net.Http] のチェック ボックスをオンにします。In the list of names, select the System.Net.Http check box.
[OK] をクリックしてダイアログ ボックスを閉じます。Choose the OK button to close the dialog box.
必要な Imports ステートメントを追加するAdd necessary Imports statements
ソリューション エクスプローラーで MainWindow.xaml.vb のショートカット メニューを開き、 [コードの表示] を選択します。In Solution Explorer, open the shortcut menu for MainWindow.xaml.vb, and then choose View Code.
次の
Imports
ステートメントが存在しない場合は、コード ファイルの先頭に追加します。Add the followingImports
statements at the top of the code file if they’re not already present.Imports System.Net.Http Imports System.Net Imports System.IO
同期アプリケーションを作成するCreate a synchronous application
デザイン ウィンドウの MainWindow.xaml で、 [Start] ボタンをダブルクリックして、MainWindow.xaml.vb に
startButton_Click
イベント ハンドラーを作成します。In the design window, MainWindow.xaml, double-click the Start button to create thestartButton_Click
event handler in MainWindow.xaml.vb.MainWindow.xaml.vb で、次のコードを
startButton_Click
の本文にコピーします。In MainWindow.xaml.vb, copy the following code into the body ofstartButton_Click
:resultsTextBox.Clear() SumPageSizes() resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
このコードは、
SumPageSizes
アプリケーションを実行するメソッドを呼び出し、startButton_Click
に制御が戻るとメッセージを表示します。The code calls the method that drives the application,SumPageSizes
, and displays a message when control returns tostartButton_Click
.同期ソリューションのコードには、次の 4 つのメソッドが含まれています。The code for the synchronous solution contains the following four methods:
SumPageSizes
は、SetUpURLList
から Web ページ URL のリストを取得し、GetURLContents
とDisplayResults
を呼び出して各 URL を処理します。SumPageSizes
, which gets a list of webpage URLs fromSetUpURLList
and then callsGetURLContents
andDisplayResults
to process each URL.SetUpURLList
は、Web アドレスのリストを作成して返します。SetUpURLList
, which makes and returns a list of web addresses.GetURLContents
は、各 Web サイトのコンテンツをダウンロードし、バイト配列としてそのコンテンツを返します。GetURLContents
, which downloads the contents of each website and returns the contents as a byte array.DisplayResults
は、各 URL のバイト配列内のバイト数を表示します。DisplayResults
, which displays the number of bytes in the byte array for each URL.
次の 4 つのメソッドをコピーし、それを MainWindow.xaml.vb の
startButton_Click
イベント ハンドラーの下に貼り付けます。Copy the following four methods, and then paste them under thestartButton_Click
event handler in MainWindow.xaml.vb:Private Sub SumPageSizes() ' Make a list of web addresses. Dim urlList As List(Of String) = SetUpURLList() Dim total = 0 For Each url In urlList ' GetURLContents returns the contents of url as a byte array. Dim urlContents As Byte() = GetURLContents(url) DisplayResults(url, urlContents) ' Update the total. total += urlContents.Length Next ' Display the total count for all of the web addresses. resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "Total bytes returned: {0}" & vbCrLf, total) End Sub Private Function SetUpURLList() As List(Of String) Dim urls = New List(Of String) From { "https://msdn.microsoft.com/library/windows/apps/br211380.aspx", "https://msdn.microsoft.com", "https://msdn.microsoft.com/library/hh290136.aspx", "https://msdn.microsoft.com/library/ee256749.aspx", "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 Private Function GetURLContents(url As String) As Byte() ' The downloaded resource ends up in the variable named content. Dim content = New MemoryStream() ' Initialize an HttpWebRequest for the current URL. Dim webReq = CType(WebRequest.Create(url), HttpWebRequest) ' Send the request to the Internet resource and wait for ' the response. ' Note: you can't use HttpWebRequest.GetResponse in a Windows Store app. Using response As WebResponse = webReq.GetResponse() ' Get the data stream that is associated with the specified URL. Using responseStream As Stream = response.GetResponseStream() ' Read the bytes in responseStream and copy them to content. responseStream.CopyTo(content) End Using End Using ' Return the result as a byte array. Return content.ToArray() End Function Private Sub DisplayResults(url As String, content As Byte()) ' 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. Dim bytes = content.Length ' Strip off the "https://". Dim displayURL = url.Replace("https://", "") resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes) End Sub
同期ソリューションをテストするTest the synchronous solution
F5 キーを押してプログラムを実行し、 [Start] を複数回クリックします。Choose the F5 key to run the program, and then choose the Start button.
次の一覧のような出力が表示されます。Output that resembles the following list should appear:
msdn.microsoft.com/library/windows/apps/br211380.aspx 383832 msdn.microsoft.com 33964 msdn.microsoft.com/library/hh290136.aspx 225793 msdn.microsoft.com/library/ee256749.aspx 143577 msdn.microsoft.com/library/hh290138.aspx 237372 msdn.microsoft.com/library/hh290140.aspx 128279 msdn.microsoft.com/library/dd470362.aspx 157649 msdn.microsoft.com/library/aa578028.aspx 204457 msdn.microsoft.com/library/ms404677.aspx 176405 msdn.microsoft.com/library/ff730837.aspx 143474 Total bytes returned: 1834802 Control returned to startButton_Click.
カウントの表示には数秒かかる点に注意してください。Notice that it takes a few seconds to display the counts. その間、要求されたリソースのダウンロードが完了するまで UI スレッドがブロックされます。During that time, the UI thread is blocked while it waits for requested resources to download. このため、 [Start] ボタンのクリック後は、表示ウィンドウの移動、最大化、最小化のほか、閉じることさえできなくなります。As a result, you can't move, maximize, minimize, or even close the display window after you choose the Start button. バイト カウントの表示が開始するまでは、これらの操作を実行しても失敗します。These efforts fail until the byte counts start to appear. Web サイトが応答していない場合、どのサイトに問題があるのかを示す情報は表示されません。If a website isn’t responding, you have no indication of which site failed. 待つのをやめて、プログラムを閉じることさえ難しい状態になります。It is difficult even to stop waiting and close the program.
GetURLContents を非同期メソッドに変換するConvert GetURLContents to an asynchronous method
同期ソリューションを非同期ソリューションに変換する際に、最初に取りかかるのに最適な場所は、
GetURLContents
内です。その理由は、HttpWebRequest.GetResponse メソッドおよび Stream.CopyTo メソッドへの呼び出しで、アプリケーションが Web にアクセスするためです。To convert the synchronous solution to an asynchronous solution, the best place to start is inGetURLContents
because the calls to the HttpWebRequest.GetResponse method and to the Stream.CopyTo method are where the application accesses the web. .NET Framework には両方のメソッドの非同期バージョンが用意されているため、変換は簡単です。The .NET Framework makes the conversion easy by supplying asynchronous versions of both methods.GetURLContents
で使用されているメソッドの詳細については、「WebRequest」を参照してください。For more information about the methods that are used inGetURLContents
, see WebRequest.注意
このチュートリアルの手順に従っていると、いくつかのコンパイラ エラーが表示されます。As you follow the steps in this walkthrough, several compiler errors appear. これらのエラーは無視することで、チュートリアルを続行できます。You can ignore them and continue with the walkthrough.
GetURLContents
の 3 行目で呼び出されるメソッドを、GetResponse
から、非同期でタスク ベースの GetResponseAsync メソッドに変更します。Change the method that's called in the third line ofGetURLContents
fromGetResponse
to the asynchronous, task-based GetResponseAsync method.Using response As WebResponse = webReq.GetResponseAsync()
GetResponseAsync
は、Task<TResult> を返します。GetResponseAsync
returns a Task<TResult>. この場合、タスク戻り変数のTResult
の型は WebResponse です。In this case, the task return variable,TResult
, has type WebResponse. このタスクは、要求されたデータのダウンロードが完了し、タスクが最後まで実行された後に、実際のWebResponse
オブジェクトを生成するという約束です。The task is a promise to produce an actualWebResponse
object after the requested data has been downloaded and the task has run to completion.タスクから
WebResponse
値を取得するには、次のコードに示すように、Await 演算子をGetResponseAsync
への呼び出しに適用します。To retrieve theWebResponse
value from the task, apply an Await operator to the call toGetResponseAsync
, as the following code shows.Using response As WebResponse = Await webReq.GetResponseAsync()
Await
演算子は、現在のメソッド、GetURLContents
の実行を、待機しているタスクが完了するまで中断します。TheAwait
operator suspends the execution of the current method,GetURLContents
, until the awaited task is complete. その間、現在のメソッドの呼び出し元に制御が戻されます。In the meantime, control returns to the caller of the current method. この例では、現在のメソッドがGetURLContents
で、呼び出し元がSumPageSizes
です。In this example, the current method isGetURLContents
, and the caller isSumPageSizes
. タスクが完了すると、約束されていたWebResponse
オブジェクトが完了したタスクの値として生成され、変数response
に割り当てられます。When the task is finished, the promisedWebResponse
object is produced as the value of the awaited task and assigned to the variableresponse
.上記のステートメントは、動作を明確にするため、次の 2 つのステートメントに分割できます。The previous statement can be separated into the following two statements to clarify what happens.
Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync() Using response As WebResponse = Await responseTask
webReq.GetResponseAsync
への呼び出しによって、Task(Of WebResponse)
またはTask<WebResponse>
が返されます。The call towebReq.GetResponseAsync
returns aTask(Of WebResponse)
orTask<WebResponse>
. その後、WebResponse
値を取得するため、タスクにAwait
演算子が適用されます。Then anAwait
operator is applied to the task to retrieve theWebResponse
value.非同期メソッドにタスクの完了に依存しない処理がある場合、メソッドはこれら 2 つのステートメントの間、つまり非同期メソッドへの呼び出しから、await 演算子の適用までの間にその処理を続行することができます。If your async method has work to do that doesn’t depend on the completion of the task, the method can continue with that work between these two statements, after the call to the async method and before the await operator is applied. たとえば、「方法:Async と Await を使用して複数の Web 要求を並列実行する (Visual Basic)」および「方法: Task.WhenAll を使用して非同期のチュートリアルを拡張する (Visual Basic)」を参照してください。For examples, see How to: Make Multiple Web Requests in Parallel by Using Async and Await (Visual Basic) and How to: Extend the Async Walkthrough by Using Task.WhenAll (Visual Basic).
前の手順で
Await
演算子を追加したため、コンパイラ エラーが発生します。Because you added theAwait
operator in the previous step, a compiler error occurs. この演算子は、Async 修飾子でマークされているメソッドでのみ使用できます。The operator can be used only in methods that are marked with the Async modifier.CopyTo
への呼び出しをCopyToAsync
への呼び出しに置き換える変換手順を繰り返す間は、エラーを無視してください。Ignore the error while you repeat the conversion steps to replace the call toCopyTo
with a call toCopyToAsync
.呼び出されるメソッドの名前を CopyToAsync に変更します。Change the name of the method that’s called to CopyToAsync.
CopyTo
またはCopyToAsync
メソッドは、その引数content
にバイトをコピーし、意味のある値は返しません。TheCopyTo
orCopyToAsync
method copies bytes to its argument,content
, and doesn’t return a meaningful value. 同期バージョンでは、CopyTo
への呼び出しは値を返さない単純なステートメントです。In the synchronous version, the call toCopyTo
is a simple statement that doesn't return a value. 非同期バージョンでは、CopyToAsync
は Task を返します。The asynchronous version,CopyToAsync
, returns a Task. タスクは "Task(void)" のように機能し、メソッドを待機できるようにします。The task functions like "Task(void)" and enables the method to be awaited. 次のコードに示すように、Await
またはawait
を、CopyToAsync
への呼び出しに適用します。ApplyAwait
orawait
to the call toCopyToAsync
, as the following code shows.Await responseStream.CopyToAsync(content)
上記のステートメントでは、次の 2 行のコードを省略しています。The previous statement abbreviates the following two lines of code.
' CopyToAsync returns a Task, not a Task<T>. Dim copyTask As Task = responseStream.CopyToAsync(content) ' When copyTask is completed, content contains a copy of ' responseStream. Await copyTask
GetURLContents
内で必要な作業として残っているのは、メソッド シグネチャの調整のみです。All that remains to be done inGetURLContents
is to adjust the method signature.Await
演算子は、Async 修飾子でマークされているメソッドでのみ使用できます。You can use theAwait
operator only in methods that are marked with the Async modifier. 次のコードに示すように、修飾子を追加し、メソッドを非同期メソッドとしてマークします。Add the modifier to mark the method as an async method, as the following code shows.Private Async Function GetURLContents(url As String) As Byte()
非同期メソッドの戻り値の型は、Task と Task<TResult> のみを指定できます。The return type of an async method can only be Task, Task<TResult>. Visual Basic でのメソッドは、
Task
またはTask(Of T)
を返すFunction
にするか、Sub
にする必要があります。In Visual Basic, the method must be aFunction
that returns aTask
or aTask(Of T)
, or the method must be aSub
. 通常、Sub
メソッドは、Sub
を必要とする非同期イベント ハンドラーでのみ使用します。Typically, aSub
method is used only in an async event handler, whereSub
is required. それ以外のケースでは、完成したメソッドに、T 型の値を返す Return ステートメントが含まれる場合はTask(T)
を使用し、完成したメソッドが意味のある値を返さない場合はTask
を使用します。In other cases, you useTask(T)
if the completed method has a Return statement that returns a value of type T, and you useTask
if the completed method doesn’t return a meaningful value.詳細については、「非同期の戻り値の型 (Visual Basic)」を参照してください。For more information, see Async Return Types (Visual Basic).
メソッド
GetURLContents
には return ステートメントがあり、このステートメントはバイト配列を返します。MethodGetURLContents
has a return statement, and the statement returns a byte array. そのため、非同期バージョンの戻り値の型は Task(T) であり、T はバイト配列です。Therefore, the return type of the async version is Task(T), where T is a byte array. メソッド シグネチャに、次の変更を加えます。Make the following changes in the method signature:戻り値の型を
Task(Of Byte())
に変更します。Change the return type toTask(Of Byte())
.規則により、非同期メソッドは "Async" で終わる名前を持つことになっているため、メソッドの名前を
GetURLContentsAsync
に変更します。By convention, asynchronous methods have names that end in "Async," so rename the methodGetURLContentsAsync
.
これらの変更を次のコードに示します。The following code shows these changes.
Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())
このいくつかの変更によって、
GetURLContents
の非同期メソッドへの変換が完了しました。With those few changes, the conversion ofGetURLContents
to an asynchronous method is complete.
SumPageSizes を非同期メソッドに変換するConvert SumPageSizes to an asynchronous method
SumPageSizes
に対して、前述した手順を繰り返します。Repeat the steps from the previous procedure forSumPageSizes
. まずは、GetURLContents
への呼び出しを非同期呼び出しに変更します。First, change the call toGetURLContents
to an asynchronous call.呼び出されるメソッドの名前を
GetURLContents
からGetURLContentsAsync
に変更します (まだ変更していない場合)。Change the name of the method that’s called fromGetURLContents
toGetURLContentsAsync
, if you haven't already done so.バイト配列値を取得するために、
Await
を、GetURLContentsAsync
が返すタスクに適用します。ApplyAwait
to the task thatGetURLContentsAsync
returns to obtain the byte array value.
これらの変更を次のコードに示します。The following code shows these changes.
Dim urlContents As Byte() = Await GetURLContentsAsync(url)
上記の割り当てでは、次の 2 行のコードを省略しています。The previous assignment abbreviates the following two lines of code.
' GetURLContentsAsync returns a task. At completion, the task ' produces a byte array. Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url) Dim urlContents As Byte() = Await getContentsTask
メソッドのシグネチャに、次の変更を加えます。Make the following changes in the method's signature:
メソッドを
Async
修飾子でマークします。Mark the method with theAsync
modifier.メソッド名に "Async" を追加します。Add "Async" to the method name.
今回、タスク戻り変数の T がない理由は、
SumPageSizesAsync
が T のための値を返さないからです (メソッドにReturn
ステートメントがありません)。ただし、メソッドは待機可能になるためにTask
を返す必要があります。There is no task return variable, T, this time becauseSumPageSizesAsync
doesn’t return a value for T. (The method has noReturn
statement.) However, the method must return aTask
to be awaitable. そのため、メソッドの型をSub
からFunction
に変更します。Therefore, change the method type fromSub
toFunction
. 関数の戻り値の型は、Task
です。The return type of the function isTask
.
これらの変更を次のコードに示します。The following code shows these changes.
Private Async Function SumPageSizesAsync() As Task
SumPageSizes
からSumPageSizesAsync
への変換が完了しました。The conversion ofSumPageSizes
toSumPageSizesAsync
is complete.
startButton_Click を非同期メソッドに変換するConvert startButton_Click to an asynchronous method
イベント ハンドラーで、呼び出されるメソッドの名前を
SumPageSizes
からSumPageSizesAsync
に変更します (まだ変更していない場合)。In the event handler, change the name of the called method fromSumPageSizes
toSumPageSizesAsync
, if you haven’t already done so.SumPageSizesAsync
は非同期メソッドであるため、結果を待機するイベント ハンドラーのコードを変更します。BecauseSumPageSizesAsync
is an async method, change the code in the event handler to await the result.SumPageSizesAsync
への呼び出しは、GetURLContentsAsync
のCopyToAsync
への呼び出しに似ています。The call toSumPageSizesAsync
mirrors the call toCopyToAsync
inGetURLContentsAsync
. この呼び出しによって、Task(T)
ではなくTask
が返されます。The call returns aTask
, not aTask(T)
.前述した手順と同様に、1 つまたは 2 つのステートメントを使用して、呼び出しを変換できます。As in previous procedures, you can convert the call by using one statement or two statements. これらの変更を次のコードに示します。The following code shows these changes.
' One-step async call. Await SumPageSizesAsync() ' Two-step async call. Dim sumTask As Task = SumPageSizesAsync() Await sumTask
誤って操作が再入することを避けるために、次のステートメントを
startButton_Click
の先頭に追加して [Start] ボタンを無効にします。To prevent accidentally reentering the operation, add the following statement at the top ofstartButton_Click
to disable the Start button.' Disable the button until the operation is complete. startButton.IsEnabled = False
イベント ハンドラーの末尾で、ボタンを再び有効にできます。You can reenable the button at the end of the event handler.
' Reenable the button in case you want to run the operation again. startButton.IsEnabled = True
再入の詳細については、「非同期アプリにおける再入の処理 (Visual Basic)」を参照してください。For more information about reentrancy, see Handling Reentrancy in Async Apps (Visual Basic).
最後に、
Async
修飾子を宣言に追加し、イベント ハンドラーがSumPagSizesAsync
を待機できるようにします。Finally, add theAsync
modifier to the declaration so that the event handler can awaitSumPagSizesAsync
.Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
通常、イベント ハンドラーの名前は変更されません。Typically, the names of event handlers aren’t changed. 戻り値の型が
Task
に変更されていない理由は、イベント ハンドラーが、Visual Basic ではSub
プロシージャになる必要があるためです。The return type isn’t changed toTask
because event handlers must beSub
procedures in Visual Basic.同期処理から非同期処理へのプロジェクトの変換が完了しました。The conversion of the project from synchronous to asynchronous processing is complete.
非同期ソリューションをテストするTest the asynchronous solution
F5 キーを押してプログラムを実行し、 [Start] を複数回クリックします。Choose the F5 key to run the program, and then choose the Start button.
同期ソリューションの出力に似た出力が表示されます。Output that resembles the output of the synchronous solution should appear. ただし、次の相違点に注意してください。However, notice the following differences.
処理の完了後に、すべての結果が同時に表示されることはありません。The results don’t all occur at the same time, after the processing is complete. たとえば、両方のプログラムの
startButton_Click
には、テキスト ボックスをクリアする行が含まれています。For example, both programs contain a line instartButton_Click
that clears the text box. この目的は、実行ごとにテキスト ボックスをクリアすることです。1 つの結果セットが表示された後に、もう一度 [Start] ボタンをクリックすると、テキスト ボックスがクリアされます。The intent is to clear the text box between runs if you choose the Start button for a second time, after one set of results has appeared. 同期バージョンでは、2 回目のカウントが表示される直前、ダウンロードが完了して UI スレッドが他の処理を実行できる状態になったときにテキスト ボックスがクリアされます。In the synchronous version, the text box is cleared just before the counts appear for the second time, when the downloads are completed and the UI thread is free to do other work. 非同期バージョンでは、 [Start] ボタンをクリックした直後にテキスト ボックスがクリアされます。In the asynchronous version, the text box clears immediately after you choose the Start button.最も重要な点は、ダウンロード中に UI スレッドがブロックされないことです。Most importantly, the UI thread isn’t blocked during the downloads. Web リソースをダウンロード、カウント、および表示している間に、ウィンドウの移動やサイズ変更を行うことができます。You can move or resize the window while the web resources are being downloaded, counted, and displayed. いずれかの Web サイトの処理が遅い、または応答しない場合、閉じるボタン (右上隅の赤色のフィールドにある [x]) をクリックすることで、操作を取り消すことができます。If one of the websites is slow or not responding, you can cancel the operation by choosing the Close button (the x in the red field in the upper-right corner).
GetURLContentsAsync メソッドを .NET Framework メソッドに置き換えるReplace the GetURLContentsAsync method with a .NET Framework method
.NET Framework では、使用できる非同期メソッドが数多く用意されています。The .NET Framework provides many async methods that you can use. その 1 つである、HttpClient.GetByteArrayAsync(String) メソッドは、このチュートリアルに必要な処理だけを実行します。One of them, the HttpClient.GetByteArrayAsync(String) method, does just what you need for this walkthrough. これを、前述の手順で作成した
GetURLContentsAsync
メソッドの代わりに使用できます。You can use it instead of theGetURLContentsAsync
method that you created in an earlier procedure.まずは、
SumPageSizesAsync
メソッドで HttpClient オブジェクトを作成します。The first step is to create an HttpClient object in theSumPageSizesAsync
method. 次の宣言をメソッドの先頭に追加します。Add the following declaration at the start of the method.' Declare an HttpClient object and increase the buffer size. The ' default buffer size is 65,536. Dim client As HttpClient = New HttpClient() With {.MaxResponseContentBufferSize = 1000000}
SumPageSizesAsync,
で、GetURLContentsAsync
メソッドへの呼び出しをHttpClient
メソッドへの呼び出しに置き換えます。InSumPageSizesAsync,
replace the call to yourGetURLContentsAsync
method with a call to theHttpClient
method.Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
記述した
GetURLContentsAsync
メソッドを削除するかコメント アウトします。Remove or comment out theGetURLContentsAsync
method that you wrote.F5 キーを押してプログラムを実行し、 [Start] を複数回クリックします。Choose the F5 key to run the program, and then choose the Start button.
このバージョンのプロジェクトの動作は、「非同期ソリューションをテストするには」の手順で説明している動作と同じですが、さらに少ない手間で作成できます。The behavior of this version of the project should match the behavior that the "To test the asynchronous solution" procedure describes but with even less effort from you.
例Example
次に示したのは、非同期の GetURLContentsAsync
メソッドを使用する変換後の非同期ソリューションのコード例全体です。The following is the full example of the converted asynchronous solution that uses the asynchronous GetURLContentsAsync
method. この例は、元の同期ソリューションと非常によく似ています。Notice that it strongly resembles the original, synchronous solution.
' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http
Imports System.Net
Imports System.IO
Class MainWindow
Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
' Disable the button until the operation is complete.
startButton.IsEnabled = False
resultsTextBox.Clear()
'' One-step async call.
Await SumPageSizesAsync()
' Two-step async call.
'Dim sumTask As Task = SumPageSizesAsync()
'Await sumTask
resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."
' Reenable the button in case you want to run the operation again.
startButton.IsEnabled = True
End Sub
Private Async Function SumPageSizesAsync() As Task
' Make a list of web addresses.
Dim urlList As List(Of String) = SetUpURLList()
Dim total = 0
For Each url In urlList
Dim urlContents As Byte() = Await GetURLContentsAsync(url)
' The previous line abbreviates the following two assignment statements.
'//<snippet21>
' GetURLContentsAsync returns a task. At completion, the task
' produces a byte array.
'Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url)
'Dim urlContents As Byte() = Await getContentsTask
DisplayResults(url, urlContents)
' 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: {0}" & vbCrLf, total)
End Function
Private Function SetUpURLList() As List(Of String)
Dim urls = New List(Of String) From
{
"https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"https://msdn.microsoft.com",
"https://msdn.microsoft.com/library/hh290136.aspx",
"https://msdn.microsoft.com/library/ee256749.aspx",
"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
Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())
' The downloaded resource ends up in the variable named content.
Dim content = New MemoryStream()
' Initialize an HttpWebRequest for the current URL.
Dim webReq = CType(WebRequest.Create(url), HttpWebRequest)
' Send the request to the Internet resource and wait for
' the response.
Using response As WebResponse = Await webReq.GetResponseAsync()
' The previous statement abbreviates the following two statements.
'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync()
'Using response As WebResponse = Await responseTask
' Get the data stream that is associated with the specified URL.
Using responseStream As Stream = response.GetResponseStream()
' Read the bytes in responseStream and copy them to content.
Await responseStream.CopyToAsync(content)
' The previous statement abbreviates the following two statements.
' CopyToAsync returns a Task, not a Task<T>.
'Dim copyTask As Task = responseStream.CopyToAsync(content)
' When copyTask is completed, content contains a copy of
' responseStream.
'Await copyTask
End Using
End Using
' Return the result as a byte array.
Return content.ToArray()
End Function
Private Sub DisplayResults(url As String, content As Byte())
' 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.
Dim bytes = content.Length
' Strip off the "https://".
Dim displayURL = url.Replace("https://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class
次のコードには、HttpClient
の GetByteArrayAsync
メソッドを使用するソリューション例のすべてが含まれています。The following code contains the full example of the solution that uses the HttpClient
method, GetByteArrayAsync
.
' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http
Imports System.Net
Imports System.IO
Class MainWindow
Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
resultsTextBox.Clear()
' Disable the button until the operation is complete.
startButton.IsEnabled = False
' One-step async call.
Await SumPageSizesAsync()
' Two-step async call.
'Dim sumTask As Task = SumPageSizesAsync()
'Await sumTask
resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."
' Reenable the button in case you want to run the operation again.
startButton.IsEnabled = True
End Sub
Private Async Function SumPageSizesAsync() As Task
' Declare an HttpClient object and increase the buffer size. The
' default buffer size is 65,536.
Dim client As HttpClient =
New HttpClient() With {.MaxResponseContentBufferSize = 1000000}
' Make a list of web addresses.
Dim urlList As List(Of String) = SetUpURLList()
Dim total = 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)
' The following two lines can replace the previous assignment statement.
'Dim getContentsTask As Task(Of Byte()) = client.GetByteArrayAsync(url)
'Dim urlContents As Byte() = Await getContentsTask
DisplayResults(url, urlContents)
' 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: {0}" & vbCrLf, total)
End Function
Private Function SetUpURLList() As List(Of String)
Dim urls = New List(Of String) From
{
"https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"https://msdn.microsoft.com",
"https://msdn.microsoft.com/library/hh290136.aspx",
"https://msdn.microsoft.com/library/ee256749.aspx",
"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
Private Sub DisplayResults(url As String, content As Byte())
' 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.
Dim bytes = content.Length
' Strip off the "https://".
Dim displayURL = url.Replace("https://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class
関連項目See also
- Async Sample:Web へのアクセスのチュートリアル (C# および Visual Basic)Async Sample: Accessing the Web Walkthrough (C# and Visual Basic)
- Await 演算子Await Operator
- AsyncAsync
- Async および Await を使用した非同期プログラミング (Visual Basic)Asynchronous Programming with Async and Await (Visual Basic)
- 非同期の戻り値の型 (Visual Basic)Async Return Types (Visual Basic)
- タスク ベースの非同期プログラミング (TAP)Task-based Asynchronous Programming (TAP)
- 方法: Task.WhenAll を使用して非同期のチュートリアルを拡張する (Visual Basic)How to: Extend the Async Walkthrough by Using Task.WhenAll (Visual Basic)
- 方法: Async と Await を使用して複数の Web 要求を並列実行する (Visual Basic)How to: Make Multiple Web Requests in Parallel by Using Async and Await (Visual Basic)