2

次のようなログ ファイル ローテーション関数があります。

    private static void RotateLogs()
    {
        FileInfo LogFile = new FileInfo(@"C:\temp\dataTransferErrorLog.txt");

        if (LogFile.Exists && (LogFile.Length) >= 10 * 1048576)
        {
            Compress(LogFile);
            LogFile.Delete();
            File.Create(@"C:\temp\dataTransferErrorLog.txt");
        }
    }

    private static void Compress(FileInfo fi)
    {
        // Get the stream of the source file.
        using (FileStream inFile = fi.OpenRead())
        {
            // Prevent compressing hidden and 
            // already compressed files.
            if ((File.GetAttributes(fi.FullName)
                & FileAttributes.Hidden)
                != FileAttributes.Hidden & fi.Extension != ".gz")
            {
                string destFileName = fi.FullName.Substring(0, fi.FullName.LastIndexOf('.')) + System.DateTime.Now.ToString("yyyyMMddHHmm") + fi.FullName.Substring(fi.FullName.LastIndexOf('.')) + ".gz";
                // Create the compressed file.
                using (FileStream outFile =
                            File.Create(destFileName))
                {
                    using (GZipStream Compress =
                        new GZipStream(outFile,
                        CompressionMode.Compress))
                    {
                        // Copy the source file into 
                        // the compression stream.
                        inFile.CopyTo(Compress);
                    }
                }
            }
        }
    }

これにより、ログ ファイルをローテーションしようとするたびに IOException がスローされます。.gz ファイルに書き込もうとすると例外がスローされると思いますが、よくわかりません。これはスタック トレースです。

Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.IOException
Stack:
   at System.IO.__Error.WinIOError(Int32, System.String)
   at System.IO.FileStream.Init(System.String, System.IO.FileMode, System.IO.FileAccess, Int32, Boolean, System.IO.FileShare, Int32, System.IO.FileOptions, SECURITY_ATTRIBUTES, System.String, Boolean, Boolean)
   at System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare, Int32, System.IO.FileOptions)
   at System.IO.StreamWriter.CreateFile(System.String, Boolean)
   at System.IO.StreamWriter..ctor(System.String, Boolean, System.Text.Encoding, Int32)
   at System.IO.StreamWriter..ctor(System.String, Boolean)
   at System.IO.File.AppendText(System.String)
   at XRayDataTransferService.XRayDataTransferService.LogMessage(System.String)
   at XRayDataTransferService.XRayDataTransferService.RunAgent()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

圧縮された情報を .gz ファイルに書き込もうとしたときに例外がスローされていることを誰かが確認して、例外をスローする原因となっている状況について教えてもらえますか?

編集

これが LogMessage 関数です。ほとんどの場合、これは機能しますが、例外がスローされるのは、ログがローテーションされるときだけです。

static void LogMessage(string messageText)
    {
        string ErrorLogFileName = @"C:\temp\dataTransferErrorLog.txt";

        using (StreamWriter Log = File.AppendText(ErrorLogFileName))
        {
            try
            {
                Log.WriteLine("{0}: {1}", dateStamp, messageText);
            }
            catch { }
        }
    }

アップデート:

static void RunAgent()
    {
        while (!shutdown)
        {
            LogMessage("Starting data transfer...");
            errors = 0;

           // Do some data processing

            LogMessage("Finished running with " + errors.ToString() + " error(s).");

            RotateLogs();
        }
        shutdownSignal.Set();
    }

以下のコメントで述べましたが、明確にするために、実行中のスレッドは 1 つだけです。これはサービスであるため、別のスレッドにする必要がありますが、実行中のスレッドは 1 つだけです。

4

5 に答える 5

2

編集:あなたのコメントによると、私はあなたのコードを試してみて、あなたが抱えていた問題を見つけました。この行を呼び出すと、決して閉じられない がFile.Create(@"C:\temp\dataTransferErrorLog.txt");返されます。FileStreamしたがって、2 つのアプローチを使用できます。まず、それを変数に割り当て、明示的にlikeFileStreamを呼び出す必要があります。Close()FileStream

if (!LogFile.Exists)
{
        Compress(LogFile);
        LogFile.Delete();
        FileStream fs = File.Create(@"C:\Users\On\Documents\dataTransferErrorLog.txt");
        fs.Close();
}

または、後で呼び出すとFile.AppendText()存在しないファイルが作成されるため、そこにファイルを作成しないことをお勧めします。したがって、次のようにメソッドを作成することをお勧めしますRotateLogs

private static void RotateLogs()
{
    FileInfo LogFile = new FileInfo(@"C:\temp\dataTransferErrorLog.txt");

    if (LogFile.Exists && (LogFile.Length) >= 10 * 1048576)
    {
         Compress(LogFile);
         LogFile.Delete();
    }
}
于 2012-11-16T15:09:52.730 に答える
1

スタック トレースから、このコードでは例外が発生していません。あなたのLogMessage関数では、呼び出しAppendTextていますが、それが失敗している場所です。コードの先頭 (アプリのメイン エントリ ポイント) に例外ハンドラを追加し、ログに記録します (たとえば、テキスト ファイルに直接書き込むか、コンソールに書き込みます。複雑なログは作成せず、データを取得するだけです)。例外の詳細が表示されます。あなたのより多くの情報。

2 番目の提案として、log4net非常に便利なロギング ライブラリです。ローリング ファイル アペンダーが組み込まれています。構成とセットアップが簡単で、NuGet. 利用を検討してみてはいかがでしょうか。多くの製品がそうです。

于 2012-11-16T14:38:36.420 に答える
0

あるスレッドでログに何かを書き込もうとしていて、別のスレッドがログをローテーションしようとしていると思います...

何が起こっているのかをよりよく知るために、コードを変更するだけで十分です

static void LogMessage(string messageText)
{
    try
    {
        string ErrorLogFileName = @"C:\temp\dataTransferErrorLog.txt";

        using (StreamWriter Log = File.AppendText(ErrorLogFileName))
        {
            Log.WriteLine("{0}: {1}", dateStamp, messageText);
        }
     }
     catch(Exception) { throw; }
}

とにかく、最善の選択は、log4netまたはNLogとして堅牢なログライブラリを使用することです。

彼らは彼らの仕事をかなりうまくやっています

于 2012-11-16T14:49:00.770 に答える
0

アセンブリと共に pdb をデプロイすると、スタック トレースに行番号が表示されるため、例外がスローされている場所を特定できます。あなたはpdbを生成しますよね?

于 2012-11-16T14:34:16.743 に答える
0

回転機能にはありません。私にとっては、ローテーションを行っているように見えますが、同時にファイルに追加したい (ログを書き込むため) ため、クラッシュします。

ただし、例外メッセージを投稿すると、すべてがクリアされます

于 2012-11-16T14:34:42.583 に答える