環境 :
Visual Studio 2012 Beta
こんにちは。
.NET ラボ で、セッションを聞いていただいた皆様、ありがとうございました。
「Q & A は懇親会で」と思っていたんですが、子供が夕方に高熱を出して、急遽、懇親会の参加ができなくなってしまいました。すみませんでした。
セッションの最後で説明した Web Form と WCF の async メソッドについて、説明が駆け足になりすぎて手順が説明できなかったので、本ブログにて補足しておきます。(主要な話は、「.NET で非同期 (Async) がなぜ重要なのか」 のほうに記載してますので、ゆっくりとお試しください。)
ASP.NET MVC、ASP.NET Web API だけでなく、Web Forms、WCF などについても、下記の通り、非同期に対応しています。
ASP.NET Web Forms 4.5 の async メソッド
ASP.NET Web Form でも、Thread Pool を有効活用する async メソッドが構築できますが、説明した通り、ちょっと特殊な書き方になります。
まず、Page ディレクティブに、下記 太字を追加しておきます。
<%@ Page title='' ... Async="true" %>
さらに、Web.config に、以下を記述します。
<configuration> <appSettings> . . . <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> . . .</configuration>
説明した通り、async キーワードを付けて、Page_Load や、Button1_Click などを実装したくなりますが、現 Beta 段階では、こうしたプログラミングは不可能です。従来通り、.NET 4 でサポートされていた Page.RegisterAsyncTask メソッドを使用して、非同期メソッドを登録する必要があります。
ただし、.NET 4.5 では、PageAsyncTask コンストラクタとして、PageAsyncTask(Func<Task> handler) が使えるようになっています。このため、以下の通り、async / await を使ってスッキリと記述できます。
protected void Page_Load(object sender, EventArgs e){ Page.RegisterAsyncTask(new PageAsyncTask(async () => { HttpClient cl = new HttpClient(); HttpResponseMessage res = await cl.GetAsync(@"http://testsite/HeavyPage/"); Label1.Text = res.ToString(); }));}
WCF 4.5 の async メソッド
こちら、実は、Parallel Programming Team のブログ に簡単に書かれているのですが (MSDN には、まだ載っていないようです)、.NET Framework 4.5 の WCF では Task を返すことが可能になっています。
このため、ASP.NET MVC などと同じく、非同期 (async) を使用した Thread Pool の有効活用が容易になっています。(ちなみに、WCF では、Worker Thread ではなく、Thread Pool の IO Thread が使用されます。)
下記のコードは、.NET 4 の WCF で可能だった非同期パターン (AsyncPattern = true) のプログラミング スタイルではありません。以前 述べたように、Task を使った同期に近いプログラミング スタイルで、非同期処理によって、スレッドの占有を無くす効率的なプログラム コードになっています。
[ServiceContract]public interface IService1{ [OperationContract] Task<string> GetDataAsync();}public class Service1 : IService1{public async Task<string> GetDataAsync(){HttpResponseMessage res = await GetHeavyPage();return res.ToString();}private Task<HttpResponseMessage> GetHeavyPage(){HttpClient cl = new HttpClient();return cl.GetAsync(@"http://localhost/HeavyWeb/");}}
上記のメソッドの名称 (GetDataAsync) に注意してください。
WCF 4.5 では、「WCF 4.5 新機能」 で述べたように、クライアント アプリケーションで [サービス参照の追加] (SvcUtil.exe) をおこなうと、非同期用のメソッド (…Async という名前のオペレーション) が構築されます。例えば、「GetData」という名前のオペレーションがサーバーで提供されている場合、クライアント側では GetData と GetDataAsync という 2 つのオペレーションが生成されます。
しかし、上記のサービスを参照追加した場合、クライアント側で「GetDataAsyncAsync」が生成されるのではなく、「GetData」と「GetDataAsync」という 2 つのオペレーションが提供されます。注意していただきたいのは、これら (GetData と GetDataAsync) は、いずれも、クライアント側における同期 / 非同期パターンのオペレーションであり、いずれのオペレーションを使用しても、サーバー側では、スレッドの無駄使いをしない効率的な非同期動作となります。(サーバー側とクライアント側を混同しないように注意してください。)
なお、WCF Data Services は、ご存じの通り、WCF の REST (WebHttp) を使って実装されています。この WCF Data Services で動作を確認したところ、残念ながら、検索している間、Thread Pool の Thread (IO Thread) がずっと握られていました。 (.NET 4.5 Beta で確認。) 少なくとも Beta 段階では、WCF Data Services で、この非同期の仕組みは使われていないようです。(このため、WCF Data Services で、あまり時間のかかるクエリーは実行しないようにしましょう。スレッドがどんどん溜まっていく可能性があります。)
ということで、.NET Framework 4.5 における サーバー側の 非同期メソッドの対応状況をまとめると、以下のような感じになります。
ASP.NET WebForms | OK |
ASP.NET MVC | OK |
ASP.NET Web API | OK |
WebSocket | OK |
WCF | OK |
WCF Data Services | N/A |
Categories: Uncategorized
初めまして
現在、下記サイトを作っているのですが、
http://www.wiredblogs.com/landing.aspx
人が足らないため、協力者を求めています。
このサイトに関しては、google mapのAPIの知識、デザイン作成が必要となっております。
もし、可能であれば、ご協力をお願いしたいと思って連絡を致しました。
可能であれば、ご連絡をお願いします。
マッテオ・マルティーニ
matteomartini72(at)yahoo(dot)com
LikeLike