1

文字列をログに記録するロガー、静的クラスを持つ静的クラスを作成したので、インスタンスを作成することなくプロジェクト全体から呼び出すことができます。とてもいいのですが、ファイルへのアクセスには時間がかかるため、別のスレッドで実行したい

どういうわけかそれは可能ですか、それを行う最良の方法は何ですか?

少し短い説明ですが、アイデアが明確になることを願っています。そうでない場合は、お知らせください。

前もって感謝します!

ちなみに、私のコードの他の改善も歓迎されていますが、すべてが可能な限り効率的ではないと感じています。

internal static class MainLogger
    {
        internal static void LogStringToFile(string logText)
        {
            DateTime timestamp = DateTime.Now;
            string str = timestamp.ToString("dd-MM-yy  HH:mm:ss ", CultureInfo.InvariantCulture) + "\t" + logText + "\n";
            const string filename = Constants.LOG_FILENAME;
            FileInfo fileInfo = new FileInfo(filename);
            if (fileInfo.Exists)
            {
                if (fileInfo.Length > Constants.LOG_FILESIZE)
                {
                    File.Create(filename).Dispose();
                }
            }
            else
            {
                File.Create(filename).Dispose();
            }
            int i = 0;
            while(true)
            {
                try
                {
                    using (StreamWriter writer = File.AppendText(filename))
                    {
                        writer.WriteLine(str);
                    }
                    break;
                }
                catch (IOException)
                {
                    Thread.Sleep(10);
                    i++;
                    if (i >= 8)
                    {
                        throw new IOException("Log file \"" + Constants.LOG_FILENAME + "\" not accessible after 5 tries");
                    }
                }
            }
        }
    }
enter code here
4

5 に答える 5

3

これを演習として行う場合 (既製のロガーを使用することはオプションではありません)、プロデューサー/コンシューマー システムを試すことができます。

  1. ロガー用の関数を作成するか、静的コンストラクターを使用します。その中で、ループを実行するだけInitの new を起動します。System.Threading.Threadwhile(true)
  2. 新しいQueue<string>ものを作成し、ロギング関数をその上にエンキューします。
  3. ループwhile(true)はキューの項目を探し、それらをデキューし、ログに記録します。
  4. いずれかのスレッドで何かを行う前に、必ずキューをロックしてください。
于 2010-06-02T13:02:12.513 に答える
3

申し訳ありませんが、車輪を再発明することはできません。ロガーとしてlog4net (またはその他の (エンタープライズ) ロギング エンジン) を
選択してください。

于 2010-06-02T12:57:28.743 に答える
1

OK、簡単に言えば、ThreadSafe 静的クラスを作成する必要があるということです。以下にいくつかのコード スニペットを示します。これは、任意のスレッドから呼び出すデリゲートです。これは正しいスレッドを指し、次に WriteToFile 関数を呼び出します。

ログを記録するアプリケーションを開始するときに、次のように渡します。ここで、LogFile はログ ファイルのファイル名とパスです。

Log.OnNewLogEntry += Log.WriteToFile (LogFile, Program.AppName);

次に、これを静的 Logging クラス内に配置します。ウィザード ビットは ThreadSafeAddEntry 関数です。これにより、コード行を書き出すための正しいスレッドにいることが保証されます。

public delegate void AddEntryDelegate(string entry, bool error);

public static Form mainwin;

public static event AddEntryDelegate OnNewLogEntry;

public static void AddEntry(string entry) {
  ThreadSafeAddEntry( entry, false );
}

private static void ThreadSafeAddEntry (string entry, bool error)
    {
    try
        {
        if (mainwin != null && mainwin.InvokeRequired)  // we are in a different thread to the main window
            mainwin.Invoke (new AddEntryDelegate (ThreadSafeAddEntry), new object [] { entry, error });  // call self from main thread
        else
            OnNewLogEntry (entry, error);
        }
    catch { }
    }

public static AddEntryDelegate WriteToFile(string filename, string appName) {
    //Do your WriteToFile work here
    }
}

そして、いよいよ一筆書き…。

Log.AddEntry ("Hello World!");
于 2010-06-02T13:10:52.940 に答える
0

まず第一に、ロギング メカニズムは通常、例外をスローしないようにする必要があります。頻繁にログに記録するメカニズムはエラーが書き込まれる場所であるため、エラーが発生し始めると状況が悪化します。

ロギングを実行できるスレッドを分岐できるようにするため、 BackgroundWorkerクラスを調べます。そうすれば、アプリの速度が低下することはなく、発生した例外は単純に無視されます。

于 2010-06-02T13:02:10.533 に答える
0

この場合、一般的な生産者と消費者のシナリオがあります。多くのスレッドがログ エントリを生成し、1 つのスレッドがそれらをファイルに書き込みます。MSDN には、このシナリオのサンプル コードを含む記事があります。

于 2010-06-02T13:00:26.213 に答える