| 2003年10月9日
『どっとねっとと雑多な日々 13』
今回は、.NET での非同期処理について書きます。
データベースの処理を非同期にするのは何通りか方法があります。Delegate にするとか、XML Web Service
を使うなど。
XML Web Service 自体には非同期処理の機能はないのですが、XML Web Serivice Client(
Web 参照で追加した Proxy クラス)には非同期処理の機能がインプリメントされますので今回は取り上げません。
では、Delegate を使う場合はどうするのかというと自前で実装します。
まず、非同期処理をするためのクラスを作成します。
using System;
using System.Threading;
using System.Data;
using System.Data.SqlClient;
namespace AsyncClient
{
/// <summary>
/// Database の概要の説明です。
/// </summary>
public class Database
{
public Database()
{
//
// TODO: コンストラクタ ロジックをここに追加してください。
//
}
public string AsyncExcetute(int count, out int threadId)
{
string message = "";
threadId = AppDomain.GetCurrentThreadId();
using(SqlConnection sc = new SqlConnection("Data Source=(local);Initial
Catalog=Samples;Trusted_Connection=yes"))
using(SqlCommand scd = new SqlCommand("INSERT INTO tblSample(SampleValue)
VALUES(@now)", sc))
{
try
{
sc.Open();
SqlParameter spNow =new SqlParameter("@now", SqlDbType.DateTime);
scd.Parameters.Add(spNow);
for(int i = 0; i < count; i++)
{
spNow.Value = DateTime.Now;
scd.ExecuteNonQuery();
}
sc.Close();
message = "完了";
}
catch(SqlException se)
{
throw se;
}
}
return message;
}
}
// 非同期 Delegate
public delegate string AsyncDelegate(int count, out int threadId);
}
これを見ていただくとわかると思うのですが、public delegate string AsyncDelegate(int
count, out int threadId);と Delegate を指定しています。
またこの Delegate を非同期処理をしたいメソッド( AsyncExecute )と同じ引数、戻り値を持っています。
次にこの非同期処理をする側の制御ロジックを作成します。
private void cmdExecute_Click(object sender, System.EventArgs
e)
{
int threadId;
AsyncClient.Database database = new AsyncClient.Database();
AsyncClient.AsyncDelegate ad = new AsyncClient.AsyncDelegate(database.AsyncExcetute);
IAsyncResult ar = ad.BeginInvoke(2000, out threadId, null, null);
while(ar.IsCompleted != true)
{
System.Threading.Thread.Sleep(10);
System.Console.Write(".");
Response.Flush();
}
string result = ad.EndInvoke(out threadId, ar);
System.Console.WriteLine(result);
}
これは、処理が完了するまでポーリングして、処理が終了するまで待機するやり方です。
ほかにも CallBack や WaitHandle を使った方法もありますので、詳細は
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpguide/html/cpovrasynchronousprogrammingoverview.asp
を参照してください。
と、ここまで非同期処理の内容を書きましたが ASP.NET での非同期処理は話が違ってきます。ASP.NET は基本的に同期処理を主眼に置いたもので、ASP.NET
で非同期処理を実現することは難しいです。なぜ、難しいのかというと、サーバサイドで非同期実行しても、Http の Response
がバッファリングされているため、ブラウザに応答が返せないという問題があり、時間がかかる処理をするとサーバサイドのタイムアウトとクライアントサイドのタイムアウトのどちらかが発生してしまうからです。
ではどうするのか?ということになると思います。実現する方法として、HttpHandler で非同期処理を実装することになると思います。非常に難しいサンプルですがこういうものもありますので、もし非同期処理を実装しなければならない場合には参考にしてください。
http://lists.ximian.com/archives/public/mono-patches/2002-August/006099.html
MSDN Library
[.NET 開発]
+ [.NET Development (英語)]
+ [ASP.NET]
+ [Technical Articles]
+ [HTTP Pipelines: Securely Implement Request Processing, Filtering,
and Content Redirection with HTTP Pipelines in ASP.NET]
|