2

これは私を少し狂わせているので、誰かが助けてくれるなら、私はとても感謝しています!!

自分の情報をログ ファイルに記録しようとしているので、Logger クラスを使用しました。

** Logger.cs **

 public  class Logger : IDisposable
{
    private readonly FileStream _file; //Only this instance have a right to own it
    private readonly StreamWriter _writer;
    private readonly object _mutex; //Mutex for synchronizing

    /// <summary>
    /// Call this function to use the text file
    /// </summary>
    /// <param name="logPath"></param>
    public Logger(string logPath)
    {
        if (logPath != null) _file = new FileStream(logPath, FileMode.Append);
        _writer = new StreamWriter(_file);
        _mutex = new object();
    }

    // Log is thread safe, it can be called from many threads
    public void Log(string message)
    {
        lock (_mutex)
        {
           //_writer.Write("\r\nLog Entry : ");
           // _writer.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
           //DateTime.Now.ToLongDateString());

            _writer.WriteLine("{0} {1}", DateTime.Now.ToString("yyyy-MM-dd"),
          DateTime.Now.ToLongTimeString());
            _writer.WriteLine(message);
        }
    }

    /// <summary>
    /// Call this function when it says file is already been using somewhere
    /// </summary>
    public void Dispose()
    {
        _writer.Dispose(); //Will close underlying stream
    }
}

** Logger クラスを使用した私のアプリケーション **

private void button1_Click(object sender, EventArgs e)
    {
        // This is the file path after d://dashboardLogfiles
        String filePath = string.Format("{0:yyyy-MM-dd}", DateTime.Now);

        // This is the text file created with time stamps
        String txtFile = string.Format("DataSummarisation{0:yyyy-MM-dd hh-mm-ss-tt}", DateTime.Now);
        // Given in config to read the path 
        var localhostizedLetter = @"d:/";
        //Create directory
        string pathString = Path.Combine(localhostizedLetter, "DataSummarisationLogfiles");
        if (!Directory.Exists(pathString))
        {
            Directory.CreateDirectory(pathString);
        }
        // Create a folder inside directory 
        // If folder exists dont create it 
        pathString = Path.Combine(pathString, filePath);
        if (!Directory.Exists(pathString))
        {
            Directory.CreateDirectory(pathString);
        }

        // create a file inside d://DataSummarisationDatetime.now//datetimewithtimestamp.txt
        // if exists please dont create it.
        pathString = Path.Combine(pathString, txtFile);
        if (!Directory.Exists(pathString))
        {
            // here my file is created and opened.
            // so I m doing a try catch to make sure if file is opened we are closing it so that nother process can use it
            File.Create(pathString).Dispose();
            var fileInfo = new FileInfo(pathString);
           // IsFileLocked(fileInfo);

        }

        _logger = new Logger(pathString);
        _logger.Log("Log File Created");
        _logger.Dispose();
        ThreadStart starter = () => MigrateProductStats(123, 0, pathString);
        var thread = new Thread(starter);
        thread.Start();
    }

** 同じロガー パスを使用する関数 **

 private void MigrateProductStats(object corporationIdObj, object brandIdObj, object logFilePath)
    {
         _logger = new Logger(logFilePath.ToString());
        _logger.Log("Am I still writing to same file?");
        _logger.Dispose();
        for (int i = 0; i <= 10;i++ )
        {
            DoProductStatsForCorporation(123, logFilePath.ToString());
        }

    }
    private void DoProductStatsForCorporation(int corporationId, string logFilePath)
    {
        _logger = new Logger(logFilePath);
        _logger.Log("Am I still writing to same file second time?");
        _logger.Dispose();
    }

** 上記のシナリオは機能しています **

**しかし、復元を避けるためにパスの代わりにオブジェクトを渡すことを期待しています**

  ThreadStart starter = () => MigrateProductStats(123, 0, _logger);
    var thread = new Thread(starter);
    thread.Start();

上記のボタン クリックのケースでは、ロガーを破棄し、関数 DoProductStatsForCorporation および MigrateProductStats へのパスを送信しています。その代わりに、破棄せずに _logger オブジェクトを送信し、子関数で Reiniate を回避しようとすると、別のプロセスで使用されているファイル。

それが理にかなっていることを願っています!

私はこれでどこに行くべきかについてかなり行き詰まっているので、これに関するガイダンスは大歓迎です。

4

3 に答える 3

2

あなたが抱えている問題は、それがMTであり、おそらくすでに開いているファイルに書き込んでいる可能性が高いことです(競合状態)

ロガー/ライターにシングルトンを使用しないのはなぜですか? 常に新しいインスタンスを作成するのではなく、ライターをロックして、1 つのインスタンスのみを使用しないのはなぜですか?

また、パス文字列が本当に間違っているように見えます。ファイル名の最後のミリ秒/ティックごとに吐き出すのはなぜですか?

ロギングにはシングルトン アプローチを使用することをお勧めします。必要に応じて、ロガーの静的インスタンスを作成し、書き込み時にファイルをロックし、完了時に破棄することをお勧めします。他のスレッドがそのファイルにアクセスしている間に、おそらく使用中のファイルに書き込みを行っています。ファイル名も一意であることを確認してください。コード内で考えているものとは異なる場合があります。

于 2013-10-16T11:04:52.590 に答える