2012-11-16 79 views
2

我有一个日志文件旋转功能,看起来像这样:日志文件循环IOException异常

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() 

有人可以证实,当它试图写入压缩信息的。广州文件,它是抛出异常,并告诉我的情况是什么原因造成它抛出异常?

编辑

这是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 { } 
     } 
    } 

UPDATE:

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(); 
    } 

我在下面的评论说,但即使这样很明显,只有一个线程在运行。这是一项服务,因此必须位于单独的线程中,但只有一个线程正在运行。

+0

你有没有尝试单步执行代码? – Derek

+1

将您的pdb文件添加到代码运行的位置,您将在堆栈跟踪中获取行号。 – pstrjds

+0

你正在使用什么日志库(如果有的话)?您是否可以开始使用NLog? –

回答

0

随您的程序集一起部署您的pdbs,您将在堆栈跟踪中获得行号,这将使您能够确定抛出异常的位置。你确实生成了pdbs,不是吗?

+0

生成PDB,但在堆栈跟踪来自时未部署。他们现在是,但数据积累的速度意味着我们不会再遇到几天的问题。 – tkooser

0

它不在旋转函数中。 对我来说,它看起来像你正在做旋转,并在同一时间你想追加到文件(写日志),所以它崩溃。

但张贴例外消息,这将清除了一切

1

从您的堆栈跟踪异常没有在此代码出现。在您的LogMessage函数中,您打电话给AppendText,那就是它失败的地方。在代码顶部添加一个异常处理程序(主应用程序入口点)并记录日志(如直接写入文本文件或写入控制台,不需要花费时间记录,只需获取数据),并且异常的详细信息会给出你更多的信息。

作为第二个建议,log4net是一个非常有用的日志记录库。它内置了滚动文件appender。通过NuGet可轻松配置和设置。你可能想考虑使用它。很多产品都有。

+0

我会看看log4net。谢谢。 – tkooser

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。

他们做的相当不错

+0

此服务不是多线程的。对ThreadStart的引用是因为它是一个服务,并且必须在它自己的线程中运行,但只有一个线程正在运行。 – tkooser

+0

@ bluesky74656它叫做什么Rotate()? – giammin

+0

它在此服务的主服务执行循环结束时被调用。在其他服务中,我已将它放在LogMessage的末尾,并得到相同的结果 – tkooser

2

编辑自己的工作:根据您的意见,我想你的代码,发现您遇到的问题。当您拨打File.Create(@"C:\temp\dataTransferErrorLog.txt");时,它会返回从未关闭的FileStream。因此您可以使用两种方法。首先,你需要的是FileStream分配给一个变量,并明确调用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(); 
    } 
}