2012年2月19日日曜日

[WP7] WebRequest で同期通信を行う

Windows Phone OS 7.1 では通信によって UI スレッドをブロックすることが無いよう、 同期通信を行うメソッドは使用を制限されています。
でも非同期通信はめんどくさいので、あまり使いたくありません。 今回は WebRequest (の GetResponse) を使いたかったのですが、 dotnet.dzone.com/news/adding-synchronous-methods では、 拡張メソッドを使って解決していました。
以下に元記事のコードを引用します。コメントは私が追記したものです。
    // クラス名は何でも良い。public static である必要がある
    public static class WebRequestExtensions
    {
        // これも public static である必要がある。仮引数は this に拡張したいクラスを続ける
        public static WebResponse GetResponse(this WebRequest request)
        {
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);

            // BeginGetResponse で autoResetEvent を発火させる
            IAsyncResult asyncResult = request.BeginGetResponse(r => autoResetEvent.Set(), null);

            // autoResetEvent.Set() の発火を待つ。すなわちここでブロックする
            autoResetEvent.WaitOne();

            return request.EndGetResponse(asyncResult);
        }

        public static Stream GetRequestStream(this WebRequest request)
        {
            AutoResetEvent autoResetEvent = new AutoResetEvent(false);

            IAsyncResult asyncResult = request.BeginGetRequestStream(r => autoResetEvent.Set(), null);

            autoResetEvent.WaitOne();

            return request.EndGetRequestStream(asyncResult);
        }
    }
以下のようにして使います。
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            // 以下と等価
            // HttpWebResponse response = (HttpWebResponse)WebRequestExtensions.GetResponse(request);
C# を始めたばかりで拡張メソッドなんて知らなかったので、実を言うと最初は下のように使っていました:-) 継承を使わずに、既存のクラスにメソッドを追加することができるんですね。 継承による拡張だと新しいクラスを定義し、既存のコードでこれに置き換える必要がありますが、 拡張メソッドではその必要がありません。
ただ、拡張メソッドを参照している箇所から定義している箇所が見えにくいので、気をつけていないと後でハマリそう。
C#、面白い。

20120226: 一部修正

0 件のコメント:

コメントを投稿