- PR -

WEBアプリケーションで自由にログを出力したい

投稿者投稿内容
naomix
ベテラン
会議室デビュー日: 2003/02/01
投稿数: 56
投稿日時: 2003-12-25 16:13
WEBアプリケーションでテキストファイルに実行履歴を出力したくて、
方法を考えたのですが、知り合いに識者がいなくて、
これでいいものかどうか判断しかねています。
ご意見をちょうだいできればありがたいです。
これは変だとか、ここは不要だとか、こっちの方がスマートだとか
何かアドバイスがあればお願いします。

実は
new Mutex(false, "LogFileLock")
の第1パラメータと
mutex.WaitOne(new TimeSpan(0,0,5), false)
の第2パラメータの意味合いを
よく理解しておりません。
falseにしてやってみたら、意図したとおりに動作したような気がしたので
falseにしているだけです。
これらのパラメータの妥当性が気になるところです。

Global.asaxの処理
コード:
//Mutexを作り、Applicationオブジェクトに格納します。
protected void Application_Start(Object sender, EventArgs e)
{
    Mutex mutex = new Mutex(false, "LogFileLock");
    Application.Add ("LogFileLock", mutex);
}

//MutexをCloseします。
protected void Application_End(Object sender, EventArgs e)
{
    Mutex mutex = (Mutex) Application["LogFileLock"];
    mutex.Close();
}



ファイル出力の処理
コード:
DateTime NowDt = DateTime.Now;//現在時刻取得
//ファイル名に本日の日付を含めます
string logFileName = "D:\\LogFile\\" + "WEB" + NowDt.ToString("yyyyMMdd") + ".log";

//ApplicationオブジェクトからMutexを取り出します。
Mutex mutex = (Mutex) Application["LogFileLock"];
if(mutex.WaitOne(new TimeSpan(0,0,5), false)) //5秒待ってダメなら何もしない
{
    try
    {
        using (StreamWriter writer = new StreamWriter(logFileName, true, Encoding.GetEncoding("Shift_JIS"))) 
        {
            writer.WriteLine(String.Format("{0:HH:mm:ss}, {1}", NowDt, "処理内容"));
        }
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}


naomix
ベテラン
会議室デビュー日: 2003/02/01
投稿数: 56
投稿日時: 2003-12-25 22:16
Mutexを使わなくてもできるのではないかと
さらに考えてみました。

最初のコードとの違いは、
Global.asaxのApplication_Startで
ただのObjectを作って、Applicationオブジェクトに格納します。
ファイル出力の処理では、
Applicationオブジェクトから
さっきのObjectを取り出して、
Monitor.TryEnterの第一パラメータとします。

一応予定通り動作しましたが、これでいいのだろうか。

私は、WEBアプリケーションのアプリケーションドメインとかスレッドが
どうなっているのかよくわかっていません。


Global.asaxの処理
コード:
protected void Application_Start(Object sender, EventArgs e)
{
    Object obj = new Object();
    Application.Add ("LogFileLock", obj);
}



ファイル出力の処理
コード:
DateTime NowDt = DateTime.Now;//現在時刻取得
//ファイル名に本日の日付を含めます
string logFileName = "D:\\LogFile\\" + "WEB" + NowDt.ToString("yyyyMMdd") + ".log";

Object obj = Application["LogFileLock"];
if(Monitor.TryEnter (obj, new TimeSpan(0,0,5))) //5秒待ってダメなら何もしない
{
    try
    {
        using (StreamWriter writer = new StreamWriter(logFileName, true, Encoding.GetEncoding("Shift_JIS"))) 
        {
            writer.WriteLine(String.Format("{0:HH:mm:ss}, {1}", NowDt, "処理内容"));
        }
    }
    finally
    {
        Monitor.Exit(obj);
    }
}


naomix
ベテラン
会議室デビュー日: 2003/02/01
投稿数: 56
投稿日時: 2003-12-26 01:17
何がしたいのかというと、要するに
ファイルの排他制御をしたいんです。
小野@どっとねっとふぁん
ぬし
会議室デビュー日: 2001/10/30
投稿数: 402
投稿日時: 2003-12-26 12:38
引用:

naomixさんの書き込み (2003-12-26 01:17) より:
何がしたいのかというと、要するに
ファイルの排他制御をしたいんです。


Application.Lock とかじゃいけないのかな。
naomix
ベテラン
会議室デビュー日: 2003/02/01
投稿数: 56
投稿日時: 2003-12-26 15:02
小野@EAC様。どうもありがとうございます。
ちょうどMonitorやMutexを用いたスレッド同期の勉強をしていたところだったので、
そればっかりに気を取られて、
Application.Lock()のことはまったく思いつきませんでした。
一部変えつつ、やってみました。

コード:
string folder = (string) Application["WebLog"];//Applicationステートに格納しておいたログファイルのフォルダを取り出す。
DateTime NowDt = DateTime.Now;//現在時刻取得
string logFileName = folder + "WEB" + NowDt.ToString("yyyyMMdd") + ".log";

Application.Lock();
using (StreamWriter writer = new StreamWriter(logFileName, true, Encoding.GetEncoding("Shift_JIS"))) 
{
    writer.WriteLine(String.Format("{0:HH:mm:ss}, {1}: {2}", NowDt, Request.Url.AbsolutePath, "TestA その1"));
    Thread.Sleep(10000);//10秒間一時停止
    writer.WriteLine(String.Format("{0:HH:mm:ss}, {1}: {2}", DateTime.Now, Request.Url.AbsolutePath, "TestA その2"));
}
Application.UnLock();



Global.asaxの処理も不要ですし、非常にシンプルでわかりやすくなりました。
無用にアプリケーションステート全体にロックを掛けてしまう点を
除けばこれも良いですね。
アプリケーションステートを使っていないシステムなら有効だと思うのですが、
Application.Lock()って
更新はもちろん読み込みにもロックが掛かりますよね。
他にアプリケーションステート使ってたら
パフォーマンスが低下してしまいます。
待ち合わせのタイムアウトを設定できないのも、残念です。
小野@どっとねっとふぁん
ぬし
会議室デビュー日: 2001/10/30
投稿数: 402
投稿日時: 2003-12-26 19:00
ログをちょっと書き込んで終了、というレベルなら
実用になるかと思うんですけどね。

まぁ、間に重い処理をいれたい、ということなら
これじゃだめですね。

で、lockステートメントはどうだったっけな。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2003-12-27 01:26
ログ出力するクラスに静的なメンバを入れて、lock もしくは Monitor を使うとかやってしまいそうです。
ログ出力の同期くらいにはあまり Application は使いたくなかったり…
あるいは、出力ファイルのフルパスをハッシュした値を元に Mutex を使ってみたりとか…
naomix
ベテラン
会議室デビュー日: 2003/02/01
投稿数: 56
投稿日時: 2003-12-27 15:59
小野@EAC様。ありがとうございます。
こちらの要件としても
ログをちょっと書き込むだけなのですが、
やはり無用にアプリケーションステート全体にロックを掛けてしまうのが
どうしても気になります。

lockステートメントは
Monitor.EnterとMonitor.Exitの組み合わせと同じです。

スキルアップ/キャリアアップ(JOB@IT)