チュートリアル: Async と Await を使用した Web へのアクセス (C# および Visual Basic)
Visual Studio 2012で導入された機能を使用して非同期のプログラミングを簡単かつ直感的に記述できます。同期コードのようになります。は、コンパイラが非同期コードは困難必要なコールバック関数、継続を処理できる非同期コードを記述できます。
単一の機能に関する詳細については、Async および Await を使用した非同期プログラミング (C# および Visual Basic)を参照してください。
サイトのリストのバイト数を合計する同期の Windows Presentation Foundation (WPF) のアプリケーションでこのチュートリアルの開始。チュートリアルでは、非同期ソリューションに新しい機能を使用してアプリケーションを変換します。
独自のアプリケーションをビルドするには、"Async サンプルをダウンロードできます: Web のチュートリアルで、C および (Visual Basic) " の 開発者コード サンプルアクセス。
このチュートリアルでは、次のタスクを実行します:
Create a WPF application.
Design a simple WPF MainWindow window.
Add a reference.
Add Imports statements or using directives.
Create a synchronous solution.
Test the synchronous solution.
Convert GetURLContents to an asynchronous method.
Convert SumPageSizes to an asynchronous method.
Convert startButton_Click to an asynchronous method.
Test the asynchronous solution.
Replace GetURLContentsAsync with a .NET Framework method.
Complete Code Examples from the Walkthrough
必須コンポーネント
Visual Studio 2012 は、コンピューターにインストールされている必要があります。詳細については、Microsoft Web サイトを参照してください。
WPF アプリケーションを作成するには
Visual Studio を起動します。
メニュー バーで [ファイル]、[新規]、[プロジェクト] の順にクリックします。
[新しいプロジェクト] ダイアログ ボックスが表示されます。
[インストールされたテンプレート] のペインで、[Visual Basic] か [Visual C#] を選択し、プロジェクトの種類の一覧 [WPF アプリケーション] を選択します。
[名前] のテキスト ボックスに、AsyncExampleWPFを入力し、を [OK] のボタンをクリックします。
ソリューション エクスプローラーに新しいプロジェクトが表示されます。
簡単な WPF MainWindow をデザインするには
Visual Studio では、エディターを選択します [MainWindow.xaml] のタブを参照してください。
[ツールボックス] のウィンドウが表示されない場合は、[ビュー] のメニューを開き、[ツールボックス] を選択します。
[MainWindow] のウィンドウに [ボタン] のコントロールと [テキスト ボックス] のコントロールを追加します。
[テキスト ボックス] のコントロールを、[プロパティ] のペインで強調表示し、次の値を設定します:
resultsTextBoxに [名前] のプロパティを設定します。
250 に [高さ] のプロパティを設定します。
500 に [幅] のプロパティを設定します。
[テキスト] のタブで、Lucida のコンソールなどの monospaced フォントを指定した場合は、グローバル Monospace。
[ボタン] のコントロールを、[プロパティ] のペインで強調表示し、次の値を設定します:
起動ボタンに [名前] のプロパティを設定します。
[ボタン] から [開始] に [コンテンツ] のプロパティの値を変更します。
両方の [MainWindow] のペインに表示されるようにテキスト ボックスとボタンを設定します。
WPF XAML デザイナーの詳細については、XAML デザイナーを使用した UI の作成を参照してください。
参照を追加するには
[ソリューション エクスプローラー] で、プロジェクトの名前が強調表示されます。
メニュー バーで、プロジェクト、[参照の追加] を選択します。
[参照マネージャー] のダイアログ ボックスが表示されます。
ダイアログ ボックスの上部に、プロジェクトが .NET Framework 4.5 を対象とすることを確認します。
[アセンブリ] の領域で、が選択されていない場合は [フレームワーク] を選択します。
名前の一覧で、[System.Net.Http] のチェック ボックスをオンにします。
ダイアログ ボックスを閉じるに [OK] のボタンをクリックします。
必要な Imports ステートメントまたは using ディレクティブを追加するには
[ソリューション エクスプローラー] では、MainWindow.xaml.cs のショートカット メニューを開き、[コードの表示] を選択します。
存在しない場合はコード ファイルの先頭に Imports の次のステートメント (Visual Basic) またはディレクティブ (using、C) を追加します。
Imports System.Net.Http Imports System.Net Imports System.IO
using System.Net.Http; using System.Net; using System.IO;
同期アプリケーションを作成するには
デザイン ウィンドウで、MainWindow.xaml は、MainWindow.xaml.cs の startButton_Click のイベント ハンドラーを作成するには [開始] のボタンをダブルクリックします。または、[開始] のボタンを強調表示するように、[プロパティ] のウィンドウの [Event handlers for the selected elements] のアイコンを選択し、[クリック] のテキスト ボックスに startButton_Click を入力します。
MainWindow.xaml.cs で、startButton_Clickの本体に、次のコードをコピーします。
resultsTextBox.Clear() SumPageSizes() resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
resultsTextBox.Clear(); SumPageSizes(); resultsTextBox.Text += "\r\nControl returned to startButton_Click.";
コードは、コントロールが startButton_Clickに戻ると、アプリケーション SumPageSizesを促進し、メッセージを表示するメソッドを呼び出します。
同期ソリューションのコードは、次の 4 種類のメソッドが含まれています:
SumPageSizesの SetUpURLList から Web ページの URL の一覧を取得し、各 URL を処理するには GetURLContents と DisplayResults を呼び出します。
SetUpURLList、Web アドレスのリストと返します。
GetURLContents、各 Web サイトのコンテンツをダウンロードし、バイト配列として内容を返します。
DisplayResults、各 URL のバイト配列のバイト数を表示します。
次の 4 とおりの方法をコピーし、MainWindow.xaml.cs の startButton_Click のイベント ハンドラーの下に貼り付けます。
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/en-us/library/hh290136.aspx", "https://msdn.microsoft.com/en-us/library/ee256749.aspx", "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 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. 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 "http://". Dim displayURL = url.Replace("http://", "") resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes) End Sub
private void SumPageSizes() { // Make a list of web addresses. List<string> urlList = SetUpURLList(); var total = 0; foreach (var url in urlList) { // GetURLContents returns the contents of url as a byte array. byte[] urlContents = GetURLContents(url); DisplayResults(url, urlContents); // Update the total. total += urlContents.Length; } // Display the total count for all of the web addresses. resultsTextBox.Text += string.Format("\r\n\r\nTotal bytes returned: {0}\r\n", total); } private List<string> SetUpURLList() { var urls = new List<string> { "https://msdn.microsoft.com/library/windows/apps/br211380.aspx", "https://msdn.microsoft.com", "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/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; } private byte[] GetURLContents(string url) { // The downloaded resource ends up in the variable named content. var content = new MemoryStream(); // Initialize an HttpWebRequest for the current URL. var webReq = (HttpWebRequest)WebRequest.Create(url); // Send the request to the Internet resource and wait for // the response. using (WebResponse response = webReq.GetResponse()) { // Get the data stream that is associated with the specified URL. using (Stream responseStream = response.GetResponseStream()) { // Read the bytes in responseStream and copy them to content. responseStream.CopyTo(content); } } // Return the result as a byte array. return content.ToArray(); } private void DisplayResults(string url, byte[] content) { // 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. var bytes = content.Length; // Strip off the "http://". var displayURL = url.Replace("http://", ""); resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes); }
同期ソリューションをテストするには
プログラムを実行するには、F5 キーを選択し、を [開始] のボタンをクリックします。
出力します。次の一覧に表示される必要がある似ています。
msdn.microsoft.com/library/windows/apps/br211380.aspx 383832 msdn.microsoft.com 33964 msdn.microsoft.com/en-us/library/hh290136.aspx 225793 msdn.microsoft.com/en-us/library/ee256749.aspx 143577 msdn.microsoft.com/en-us/library/hh290138.aspx 237372 msdn.microsoft.com/en-us/library/hh290140.aspx 128279 msdn.microsoft.com/en-us/library/dd470362.aspx 157649 msdn.microsoft.com/en-us/library/aa578028.aspx 204457 msdn.microsoft.com/en-us/library/ms404677.aspx 176405 msdn.microsoft.com/en-us/library/ff730837.aspx 143474 Total bytes returned: 1834802 Control returned to startButton_Click.
計算を表示するまでに数秒かかることに注意してください。一方、UI スレッドはダウンロードするには要求されたリソースを待っている間、ブロック。その結果 [開始] のボタンを選択すると、ウィンドウを実行し、最大化、最小化、または閉じることができません。これらの作業はバイト数を開くまで表示されません。Web サイトが応答しない場合、サイトが失敗した問題はありません。待機を停止してプログラムを閉じることは困難です。
非同期ソリューションに 例 にこの動作を比較します。
GetURLContents を非同期メソッドに変換するには
非同期ソリューションに同期ソリューションを変換するには、最適な場所は GetURLContents に開始するには HttpWebRequest のメソッド GetResponse と Stream のメソッドの呼び出しが CopyTo が Web アプリケーションにアクセスするようにであるためです。.NET Framework は、変換の両方のメソッドの非同期バージョンを指定することにより、簡単になります。
GetURLContentsで使用されるメソッドに関する詳細については、WebRequestを参照してください。
[!メモ]
このチュートリアルの手順に従うので、いくつかのコンパイル エラーが表示されます。それらは無視されます、チュートリアルに進むことができます。
GetResponse から非同期に GetURLContents の 3 番目の行に呼び出されるメソッド、GetResponseAsync のタスク ベースのメソッドを変更します。
Using response As WebResponse = webReq.GetResponseAsync()
using (WebResponse response = webReq.GetResponseAsync())
GetResponseAsync は Task<TResult> を返します。この場合、タスクは変数、TResultに、型 WebResponseがあります。タスクは、要求されたデータがダウンロードされ、タスクが完了まで実行された後 WebResponse の実際のオブジェクトを生成する約束です。
次のコードに示すように、タスクから WebResponse の値を取得するには、GetResponseAsyncの呼び出しに [Await] (Visual Basic) または 待機します。 (C#) 演算子を追加します。
Using response As WebResponse = Await webReq.GetResponseAsync()
using (WebResponse response = await webReq.GetResponseAsync())
要求の演算子は現在のメソッド、予期されるまでの GetURLContentsタスクの実行を中断して、完全です。一方、コントロールは現在のメソッド呼び出し元に返します。この例では、現在のメソッドは GetURLContentsで、呼び出し元は SumPageSizesです。タスクが終了すると、WebResponse の約束されたオブジェクトとして必要なタスクの生成、変数の値 responseに再配置。
このステートメントは、次の 2 種類のステートメントに行われる処理を明確にするために分けることができます。
'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync() 'Using response As WebResponse = Await responseTask
//Task<WebResponse> responseTask = webReq.GetResponseAsync(); //using (WebResponse response = await responseTask)
webReq.GetResponseAsync の呼び出しは Task(Of WebResponse) か Task<WebResponse>を返します。なく、演算子は WebResponse の値を取得するタスクに適用されます。
独自の非同期のメソッドにするタスクの完了に依存しない作業がある場合、メソッドは非同期のメソッドへの呼び出しの後にこれらの二つのステートメントの間にその処理と想定の演算子が適用される前に、続行できます。例については、「方法: 複数の Web 要求を並列実行する (C# および Visual Basic)」および「方法: Task.WhenAll を使用してチュートリアルを拡張する (C# および Visual Basic)」を参照してください。
前の手順の Await または await の演算子を追加したため、コンパイラ エラーが発生します。演算子は [Async] (Visual Basic) または ([async]、C) 修飾子でマークされたメソッドでのみ使用できます。CopyToAsyncにするには CopyTo への呼び出しを置き換えるに変換の手順を繰り返すときにエラーを無視します。
CopyToAsyncに呼び出されるメソッドの名前を変更します。
CopyTo または CopyToAsync のメソッドは、引数にバイト、contentをコピーし、意味のある値を返しません。同期バージョンでは、CopyTo の呼び出しは、値を返さない簡単なステートメントです。非同期バージョン、CopyToAsyncは、Taskを返します。タスク " (void) " のようなタスクの関数は待たれるするメソッドが可能になります。次のコードに示すように、CopyToAsyncの呼び出しに Await か await を適用します。
Await responseStream.CopyToAsync(content)
await responseStream.CopyToAsync(content);
このステートメントは、次の 2 行のコードを省略します。
' 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
// CopyToAsync returns a Task, not a Task<T>. //Task copyTask = responseStream.CopyToAsync(content); // When copyTask is completed, content contains a copy of // responseStream. //await copyTask;
GetURLContents でされることがあるものは、メソッドの定義を調整することです。[Async] (Visual Basic) または ([async]、C) 修飾子でマークされたメソッドでのみ Await または await の演算子を使用できます。次のコードに示すように、非同期のメソッドとしてメソッドをマークするには、修飾子を追加します。
Private Async Function GetURLContents(url As String) As Byte()
private async byte[] GetURLContents(string url)
非同期メソッドの戻り値の型は、C の Task、Task<TResult>、またはのいずれ void のみです。Visual Basic では、Task か Task(Of T)を返す場合、またはメソッドが Subである必要があります Function メソッドはである必要があります。通常、Sub のメソッド (Visual Basic) または void (C#) の戻り値の型は Sub か void が要求される async のイベント ハンドラーでのみ使用されます。それ以外の場合は、完成したメソッドに完了メソッドが意味のある値を返す T 型の値を返すと、使用 Task 場合 [Return] または 返します。 のステートメント、Task(T) を使用します。意味 "タスク (無効) として Task の戻り値の型と考えることができます"。
詳細については、「非同期の戻り値の型 (C# および Visual Basic)」を参照してください。
メソッド GetURLContents に return ステートメントとステートメントでは、バイト配列を返します。したがって、非同期のバージョンの戻り値の型は、T がバイトの配列であるタスク (T) です。メソッドの定義で次の変更を行います。:
Task(Of Byte()) (Visual Basic) または (Task<byte[]>、C) に戻り値の型を変更します。
規則により、非同期メソッドに Async "で終わる名前が付いて"、したがって、メソッド GetURLContentsAsyncの名前を変更します。
次のコードは、これらの変更について説明します。
Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())
private async Task<byte[]> GetURLContentsAsync(string url)
非同期メソッドに多少の変更によって、GetURLContents の変換が完了します。
SumPageSizes を非同期メソッドに変換するには
SumPageSizesの前の手順の手順を繰り返します。最初に、非同期呼び出しに GetURLContents への呼び出しを変更します。
いない場合、GetURLContents から GetURLContentsAsyncに呼び出されるメソッドの名前を変更します。
バイト配列の値を取得 GetURLContentsAsync を返すタスクに Await か await を適用します。
次のコードは、これらの変更について説明します。
Dim urlContents As Byte() = Await GetURLContentsAsync(url)
byte[] urlContents = await GetURLContentsAsync(url);
前の割り当ては、2 行のコードを省略します。
' 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
// GetURLContentsAsync returns a Task<T>. At completion, the task // produces a byte array. //Task<byte[]> getContentsTask = GetURLContentsAsync(url); //byte[] urlContents = await getContentsTask;
メソッドの定義で次の変更を行います。:
Async または async 修飾子のメソッドを指定します。
メソッドの名前に "Async" を追加します。
SumPageSizesAsync が T の値を返さないので、タスクの変数は、T、今度はありません。(メソッドに Return または return のステートメントはありません)。ただし、メソッドは awaitable に Task を返す必要があります。したがって、次の変更の 1 種類を作成します:
Visual Basic では、Sub から Functionにメソッドの型を変更します。関数の戻り値の型は Taskです。
では、C、void から Task、メソッドの戻り値の型を変更します。
次のコードは、これらの変更について説明します。
Private Async Function SumPageSizesAsync() As Task
private async Task SumPageSizesAsync()
SumPageSizesAsync への SumPageSizes の変換が完了します。
startButton_Click を非同期メソッドに変換するには
イベント ハンドラーで、いない場合、SumPageSizes から SumPageSizesAsyncに呼び出されるメソッドの名前を変更します。
SumPageSizesAsync が非同期のメソッドであるため、結果を待機するイベント ハンドラーのコードを変更します。
SumPageSizesAsync の呼び出しは GetURLContentsAsyncの CopyToAsync への呼び出しを反映します。呼び出しは Task、Task(T)を返します。
前の手順と同様に、1 種類の 2 種類のステートメントを使用して、呼び出しを変換できます。次のコードは、これらの変更について説明します。
'' One-step async call. Await SumPageSizesAsync() ' Two-step async call. 'Dim sumTask As Task = SumPageSizesAsync() 'Await sumTask
// One-step async call. await SumPageSizesAsync(); // Two-step async call. //Task sumTask = SumPageSizesAsync(); //await sumTask;
誤って操作を入力し直すようにするには [開始] のボタンを無効にするには startButton_Click の先頭に次のステートメントを追加します。
' Disable the button until the operation is complete. startButton.IsEnabled = False
// Disable the button until the operation is complete. startButton.IsEnabled = false;
イベント ハンドラーの末尾にボタンを再び有効にできます。
' Reenable the button in case you want to run the operation again. startButton.IsEnabled = True
// Reenable the button in case you want to run the operation again. startButton.IsEnabled = true;
再入に関する詳細については、非同期アプリにおける再入の処理 (C# および Visual Basic)を参照してください。
最後に、イベント ハンドラーが SumPagSizesAsyncを待機できるように、申告に Async または async 修飾子を追加します。
Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
private async void startButton_Click(object sender, RoutedEventArgs e)
通常、イベント ハンドラーの名前は変更されません。戻り値の型は Task にイベント ハンドラーが、C の void を返すか、または Visual Basic の Sub の手順である必要があるため、変更されません。したがって、Taskへの戻り値の型。
同期から非同期の操作へのプロジェクトの変換が完了します。
非同期ソリューションをテストするには
プログラムを実行するには、F5 キーを選択し、を [開始] のボタンをクリックします。
出力します。同期ソリューションの出力に表示される必要がある似ています。ただし、次の点に注意してください。
結果はすべて処理が完了すると、同時に実行されません。たとえば、プログラムも、startButton_Click にクリア行が含まれます。目的は 1 セットの結果が表示されたら回目の [開始] のボタンをクリックすると、実行時にテキスト ボックスをオフです。同期バージョンでは、テキスト ボックスは、ダウンロードが完了し、UI スレッドが他の作業を行って自由にある場合数回目が表示される直前に、をオフにします。非同期バージョンでは、テキスト ボックスに [開始] のボタンを選択した直後にオフにします。
何も処理なことは、UI スレッドは、ダウンロード中にブロックします。Web リソースをダウンロードしている間、数えられたり、ウィンドウを移動したり、サイズを変更できます。Web サイトの 1 つが場合は低速です、または応答しません [閉じる] のボタン (右上隅のフィールドの赤い X) をクリックして操作をキャンセルできます。
メソッドを GetURLContentsAsync .NET Framework のメソッドと置き換えるには
.NET Framework 4.5 では、を使用できる多くの非同期のメソッドを提供します。そのうちの 1 つは、HttpClient のメソッド GetByteArrayAsync(String)、このチュートリアルで必要とする処理にします。、前の手順で作成した GetURLContentsAsync のメソッドの代わりに使用できます。
まず、メソッド SumPageSizesAsyncの HttpClient のオブジェクトを作成します。メソッドの先頭に次の申告を追加します。
' 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}
// Declare an HttpClient object and increase the buffer size. The // default buffer size is 65,536. HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };
SumPageSizesAsync, で HttpClient のメソッドへの呼び出しと GetURLContentsAsync のメソッドへの呼び出しを置き換えます。
Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
byte[] urlContents = await client.GetByteArrayAsync(url);
、記述された削除するか、コメント GetURLContentsAsync のメソッドにします。
プログラムを実行するには、F5 キーを選択し、を [開始] のボタンをクリックします。
プロジェクトのこのバージョンの動作は、からの少ない労力に "非同期ソリューションの" テストするための手順で説明する動作に一致する必要があります。
例
次のコードは、記述された GetURLContentsAsync の非同期メソッドを使用して同期から非同期なソリューションへの変換の完全な例を示します。これは厳密に元の同期、ソリューションに似ています。
' 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.
' 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/en-us/library/hh290136.aspx",
"https://msdn.microsoft.com/en-us/library/ee256749.aspx",
"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
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 "http://".
Dim displayURL = url.Replace("http://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class
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 the following using directives, and add a reference for System.Net.Http.
using System.Net.Http;
using System.IO;
using System.Net;
namespace AsyncExampleWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void startButton_Click(object sender, RoutedEventArgs e)
{
// Disable the button until the operation is complete.
startButton.IsEnabled = false;
resultsTextBox.Clear();
// One-step async call.
await SumPageSizesAsync();
// Two-step async call.
//Task sumTask = SumPageSizesAsync();
//await sumTask;
resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";
// Reenable the button in case you want to run the operation again.
startButton.IsEnabled = true;
}
private async Task SumPageSizesAsync()
{
// Make a list of web addresses.
List<string> urlList = SetUpURLList();
var total = 0;
foreach (var url in urlList)
{
byte[] urlContents = await GetURLContentsAsync(url);
// The previous line abbreviates the following two assignment statements.
// GetURLContentsAsync returns a Task<T>. At completion, the task
// produces a byte array.
//Task<byte[]> getContentsTask = GetURLContentsAsync(url);
//byte[] urlContents = await getContentsTask;
DisplayResults(url, urlContents);
// Update the total.
total += urlContents.Length;
}
// Display the total count for all of the websites.
resultsTextBox.Text +=
string.Format("\r\n\r\nTotal bytes returned: {0}\r\n", total);
}
private List<string> SetUpURLList()
{
List<string> urls = new List<string>
{
"https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"https://msdn.microsoft.com",
"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/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;
}
private async Task<byte[]> GetURLContentsAsync(string url)
{
// The downloaded resource ends up in the variable named content.
var content = new MemoryStream();
// Initialize an HttpWebRequest for the current URL.
var webReq = (HttpWebRequest)WebRequest.Create(url);
// Send the request to the Internet resource and wait for
// the response.
using (WebResponse response = await webReq.GetResponseAsync())
// The previous statement abbreviates the following two statements.
//Task<WebResponse> responseTask = webReq.GetResponseAsync();
//using (WebResponse response = await responseTask)
{
// Get the data stream that is associated with the specified url.
using (Stream responseStream = 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>.
//Task copyTask = responseStream.CopyToAsync(content);
// When copyTask is completed, content contains a copy of
// responseStream.
//await copyTask;
}
}
// Return the result as a byte array.
return content.ToArray();
}
private void DisplayResults(string url, byte[] content)
{
// 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.
var bytes = content.Length;
// Strip off the "http://".
var displayURL = url.Replace("http://", "");
resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
}
}
}
次のコードは HttpClient のメソッドを使用して、ソリューション 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/en-us/library/hh290136.aspx",
"https://msdn.microsoft.com/en-us/library/ee256749.aspx",
"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
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 "http://".
Dim displayURL = url.Replace("http://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class
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 the following using directives, and add a reference for System.Net.Http.
using System.Net.Http;
using System.IO;
using System.Net;
namespace AsyncExampleWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void startButton_Click(object sender, RoutedEventArgs e)
{
resultsTextBox.Clear();
// Disable the button until the operation is complete.
startButton.IsEnabled = false;
// One-step async call.
await SumPageSizesAsync();
//// Two-step async call.
//Task sumTask = SumPageSizesAsync();
//await sumTask;
resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";
// Reenable the button in case you want to run the operation again.
startButton.IsEnabled = true;
}
private async Task SumPageSizesAsync()
{
// Declare an HttpClient object and increase the buffer size. The
// default buffer size is 65,536.
HttpClient client =
new HttpClient() { MaxResponseContentBufferSize = 1000000 };
// Make a list of web addresses.
List<string> urlList = SetUpURLList();
var total = 0;
foreach (var url in urlList)
{
// GetByteArrayAsync returns a task. At completion, the task
// produces a byte array.
byte[] urlContents = await client.GetByteArrayAsync(url);
// The following two lines can replace the previous assignment statement.
//Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
//byte[] urlContents = await getContentsTask;
DisplayResults(url, urlContents);
// Update the total.
total += urlContents.Length;
}
// Display the total count for all of the websites.
resultsTextBox.Text +=
string.Format("\r\n\r\nTotal bytes returned: {0}\r\n", total);
}
private List<string> SetUpURLList()
{
List<string> urls = new List<string>
{
"https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"https://msdn.microsoft.com",
"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/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;
}
private void DisplayResults(string url, byte[] content)
{
// 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.
var bytes = content.Length;
// Strip off the "http://".
var displayURL = url.Replace("http://", "");
resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
}
}
}
参照
処理手順
方法: Task.WhenAll を使用してチュートリアルを拡張する (C# および Visual Basic)
方法: 複数の Web 要求を並列実行する (C# および Visual Basic)
関連項目
概念
Async および Await を使用した非同期プログラミング (C# および Visual Basic)
非同期の戻り値の型 (C# および Visual Basic)
ファイル アクセスにおける非同期の使用 (C# および Visual Basic)