C# Programming

ImageHTML GET (同期と非同期パターン)

開発環境: Visual Studio 2003 

1.目次

  1. 目次
  2. 目的
  3. 参考書
  4. 同期 WEB GET アクセスパターン
  5. 非同期 WEB GET アクセスパターン
  6. ソースコード

2.目的

Web アクセス時の GETの方法を同期、非同期でそれぞれまとめました。
非同期は、マニュアルもタコだし、いいページもないしで、備忘録が必要なのでメモっています。

3.参考書

  1. GotDotNet サンプル: ”タスクの例 : POST 要求を作成する”

4.同期 WEB GET アクセスパターン

Asahi.com のページを HTML GET により同期で取得します。
非同期でないと。。。

同期で GET する場合のパターン
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Web;
using System.Net;
....
        private void Get()
        {
            Stream stream = null;
            StreamReader sr = null;

            try
            {
                WebRequest webReq = HttpWebRequest.Create( "http://www.asahi.com/home.html" );
                webReq.Method = "GET"; 
                // 1秒でタイムアウトさせる。
                webReq.Timeout = 1000; 
                // IE のプロキシ設定を使用する。
                webReq.Proxy = System.Net.WebProxy.GetDefaultProxy(); 

                WebResponse webRes = webReq.GetResponse();
                // HttpWebRequest からストリームを取得する。
                stream = webRes.GetResponseStream();
                // 1行ごとに扱いたいので、StreamReader にする。
                sr = new System.IO.StreamReader(stream, Encoding.GetEncoding("x-euc-jp"));

                string str;
                str = sr.ReadToEnd();
                Debug.WriteLine(str);
            }
            catch (Exception exc)
            {
                // わかりやすいメッセージに変える。
                throw(new Exception("xxxに接続できませんでした。"));
            }
            finally
            {
                if (sr != null) sr.Close();
                if (stream != null) stream.Close();
            }
        }

5.非同期 WEB GET アクセスパターン

Asahi.com のページを HTML GET により非同期で取得します。
1から書こうとするとはまるんですよねぇ。。。

非同期で GET する場合のパターン
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Diagnostics;
using System.Threading;
...
        public void MyCallBack(IAsyncResult ar)
        {
            Debug.WriteLine("callBack");

            HttpWebRequest req = (HttpWebRequest) ar.AsyncState;
            HttpWebResponse response = (HttpWebResponse) req.EndGetResponse(ar);

            Encoding enc = System.Text.Encoding.GetEncoding("x-euc-jp");
            StreamReader sr = new StreamReader(response.GetResponseStream(), enc);

            string str = sr.ReadToEnd();
            Debug.WriteLine(str);
            sr.Close();
            
            Debug.WriteLine("callBack End");
        }

        private void Request()
        {
            try
            {
                Debug.WriteLine("Start");
                WebRequest webReq = HttpWebRequest.Create( "http://www.asahi.com/home.html" );
                webReq.Method = "GET"; 
                // 1秒でタイムアウトさせる。
                webReq.Timeout = 1000; 
                // IE のプロキシ設定を使用する。
                webReq.Proxy = System.Net.WebProxy.GetDefaultProxy(); 
                // 非同期要求に対するコールバックを設定します。
                AsyncCallback callBack = new AsyncCallback(this.MyCallBack); 
                // 非同期で要求します。
                IAsyncResult r = webReq.BeginGetResponse(callBack, webReq);
                // 待つ場合
                // r.AsyncWaitHandle.WaitOne();
                // while(! r.IsCompleted)
                //    Debug.Write(".");
                Debug.WriteLine("Finished");
            }
            catch (Exception exc)
            {
                // わかりやすいメッセージに変える。
                throw(new WebException("xxxに接続できませんでした。" + exc.Message));
            }
        }

6.ソースコード

変更履歴
2003/5/26初版作成 V1.0 同期GET.cs、非同期GET.cs
2004/3/21タイムアウト値が1000秒になっていたのを修正。>> m_ _ m Unyoraさん

同期GET.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Web;
using System.Net;

namespace HTMLGet
{
    /// <summary>
    /// Form1 の概要の説明です。
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button button1;
        /// <summary>
        /// 必要なデザイナ変数です。
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Windows フォーム デザイナ サポートに必要です。
            //
            InitializeComponent();

            //
            // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
            //
        }

        /// <summary>
        /// 使用されているリソースに後処理を実行します。
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

                #region Windows Form Designer generated code
        /// <summary>
        /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディタで変更しないでください。
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(136, 48);
            this.button1.Name = "button1";
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                          this.button1});
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }
                #endregion

        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new Form1());
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
        Read();
        }

        private void Read()
        {
            Stream stream = null;
            StreamReader sr = null;

            try
            {
                WebRequest webReq = HttpWebRequest.Create( "http://www.asahi.com/home.html" );
                webReq.Method = "GET"; 
                // 1秒でタイムアウトさせる。
                webReq.Timeout = 1000; 
                // IE のプロキシ設定を使用する。
                webReq.Proxy = System.Net.WebProxy.GetDefaultProxy(); 

                WebResponse webRes = webReq.GetResponse();
                // HttpWebRequest からストリームを取得する。
                stream = webRes.GetResponseStream();
                // 1行ごとに扱いたいので、StreamReader にする。
                sr = new System.IO.StreamReader(stream, Encoding.GetEncoding("x-euc-jp"));

                string str;
                str = sr.ReadToEnd();
                Debug.WriteLine(str);
            }
            catch (Exception exc)
            {
                // わかりやすいメッセージに変える。
                throw(new Exception("xxxに接続できませんでした。"));
            }
            finally
            {
                if (sr != null) sr.Close();
                if (stream != null) stream.Close();
            }
        }
    }
}

非同期GET.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Diagnostics;
using System.Threading;


namespace HTMLGetAsync
{
        /// <summary>
        /// Form1 の概要の説明です。
        /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button button1;
        /// <summary>
        /// 必要なデザイナ変数です。
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Windows フォーム デザイナ サポートに必要です。
            //
            InitializeComponent();

            //
            // TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
            //
        }

        /// <summary>
        /// 使用されているリソースに後処理を実行します。
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

                #region Windows Form Designer generated code
        /// <summary>
        /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディタで変更しないでください。
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(120, 56);
            this.button1.Name = "button1";
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                          this.button1});
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }
                #endregion

        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new Form1());
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            Request();
        }

        public void MyCallBack(IAsyncResult ar)
        {
            Debug.WriteLine("callBack");

            HttpWebRequest req = (HttpWebRequest) ar.AsyncState;
            HttpWebResponse response = (HttpWebResponse) req.EndGetResponse(ar);

            Encoding enc = System.Text.Encoding.GetEncoding("x-euc-jp");
            StreamReader sr = new StreamReader(response.GetResponseStream(), enc);

            string str = sr.ReadToEnd();
            Debug.WriteLine(str);
            sr.Close();
            
            Debug.WriteLine("callBack End");
        }

        private void Request()
        {
            try
            {
                Debug.WriteLine("Start");
                WebRequest webReq = HttpWebRequest.Create( "http://www.asahi.com/home.html" );
                webReq.Method = "GET"; 
                // 1秒でタイムアウトさせる。
                webReq.Timeout = 1000; 
                // IE のプロキシ設定を使用する。
                webReq.Proxy = System.Net.WebProxy.GetDefaultProxy(); 
                // 非同期要求に対するコールバックを設定します。
                AsyncCallback callBack = new AsyncCallback(this.MyCallBack); 
                // 非同期で要求します。
                IAsyncResult r = webReq.BeginGetResponse(callBack, webReq);
                // 待つ場合
                // r.AsyncWaitHandle.WaitOne();
                // while(! r.IsCompleted)
                //    Debug.Write(".");
                Debug.WriteLine("Finished");
            }
            catch (Exception exc)
            {
                // わかりやすいメッセージに変える。
                throw(new WebException("xxxに接続できませんでした。" + exc.Message));
            }
        }
        }
}