0

基本的なロギング クラスを実装しましたが、その新しいインスタンスを作成しようとすると、次の例外が発生します。

別のプロセスで使用されているため、プロセスはファイル 'C:\Users\carl\Desktop\My Projects\TCV2\CallPotential.UI\bin\Debug\application.log' にアクセスできません。

以下は、ロガー クラスのコードです。

using System;
using System.IO;
using System.Reflection;

namespace CallPotential.Utilities
{
    public class Logger : IDisposable
    {
        /// <summary>
        /// Used to write output to the log file.
        /// </summary>
        private StreamWriter _stream;

        /// <summary>
        /// The absolute path to the log files location.
        /// </summary>
        public String LogFileName
        {
            get
            {
                // get the directory where our main assembly is located.
                Assembly assembly = Assembly.GetExecutingAssembly();
                String directoryName = Path.GetDirectoryName(assembly.Location);
                return Path.Combine(directoryName, "application.log");
            }
        }

        /// <summary>
        /// Creates a new instance of the Logger class
        /// </summary>        
        public Logger()
        {         
           _stream = new StreamWriter(LogFileName);         
        }

        /// <summary>
        /// Writes a message out to the application log file.
        /// </summary>
        /// <param name="message">The message to write to the log file.</param>
        public void Write(String message)
        {
            _stream.WriteLine(message);
            _stream.Flush();
            _stream.Close();
        }

        /// <summary>
        /// Writes a message including the applications state to the log file.
        /// </summary>
        /// <param name="state">The application state at the time of the logged message.</param>
        /// <param name="message">The message to be written to the log file.</param>
        public void Write(AppState state, String message)
        {
            Write(String.Format("{0}\r\n\t{1}", state, message));
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        public void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_stream != null)
                {
                    _stream.Dispose();
                    _stream = null;
                }
            }
        }
        ~Logger()
        {
            Dispose(false);
        }
    }
}

理由は確かですが、コンストラクターで例外がスローされます。これを理解するための助けをいただければ幸いです。

4

5 に答える 5

3

基本的な問題は、ストリームを開いたままにしておくことです。つまり、何らかの変更を加えない限り、ロギング クラスの 1 つのインスタンスにしかアクセスできません。

次のようなさまざまな変更を行うことができます。

1) 各インスタンスが独自のログ ファイル名を生成することを確認します。

2) アプリケーション全体で使用される特定のファイル名にすべてのロギングを強制的に記録します。

どちらの場合でも、SyncLock ブロックを使用して、開く、閉じる、読み取る、書き込むなどの重要な機能へのアクセスを制御して、スレッドからログを記録している場合、または複数のインスタンスが同じファイルを共有している場合に、1 つの呼び出し元のみが実行されるようにする必要があります。コードを同時に。

最初のケースでは、おそらく 1 つのインスタンスのみが必要です。

2 番目のケースでは、クラスの新しいインスタンスを作成する必要がないため、静的ストリームライターと静的メソッドを使用できます。これは、初期の例外処理アプリケーション ブロックで Microsoft からのガイダンスに基づいて、何年も前に実装したアプローチです。

于 2012-08-06T21:27:32.867 に答える
1

その新しいインスタンスを作成しようとすると、次の例外が発生します。

新しいインスタンスを作成する前に、現在のインスタンスを破棄する必要があります。

たぶん、シングルトンパターンを検討する必要があります。

于 2012-08-06T21:21:13.003 に答える
0

ロガーのインスタンスは 1 つしか持てません。ただし、Visual Studio アプリケーションはおそらくリフレクションを介してインスタンスを作成しているため、IntelliSense を使用できます。a) ホスティング プロセスをオフにします。b) コマンド ライン コンパイルを使用します。

特定の問題を解決するには、ただし設計が悪いです。

于 2012-08-06T21:36:40.993 に答える
0

私は常にログに追加プロパティを使用するので、ストリームを開くことを決して忘れないでください

    public void Write(AppState state, String message)
    {

        StreamWriter sw = new StreamWriter(LogFileName, true);// true to append the new text
        sw.WriteLine(String.Format("{0}\r\n\t{1}", state, message));
        sw.Close(); // Close() is the same as Dispose()
    }
于 2012-08-06T21:23:02.970 に答える
0

エラーを再現できました-2行目で例外がスローされました:

var logger1 = new Logger();
var logger2 = new Logger();

ただし、最初のインスタンスで Write() メソッドを使用すると、次のようになります。

var logger1 = new Logger();
logger1.Write("XYZ");
var logger2 = new Logger();

例外はスローされなくなりました。あなたの場合も同じように動作しますか?

問題は、両方のロガーに同じファイルを使用しており、ストリームを閉じたり最初のインスタンスを破棄したりしない場合、基本的に 1 つのファイルに対して同時に 2 つのストリームを開こうとすることです。

2 つの異なるファイルを使用してみてください (たとえば、デフォルト値のプロパティを持つ代わりに、コンストラクターでログ ファイルへのパスを渡すことができます)。それで問題が解決したかどうかをお知らせください。

PSただし、両方のロガーが同じファイルに書き込む必要があり、同時にファイルにアクセスできる必要がある場合は、別のアプローチを取る必要があります-シングルトンパターンがより適切です。

于 2012-08-06T21:32:29.367 に答える