2013-10-16 37 views
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(); 
    } 

**以上场景正在运行**

**但是我期待传递对象,而不是路径,以避免Reinstatiaitng **

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

在我的按钮上面的情况下单击我处置记录器和发送,而不是该路径功能DoProductStatsForCorporation和MigrateProductStats如果我尝试发送_logger对象而不处理这个,并且避免在我的子函数中使用Reiniate,那么我得到的错误不能写入该文件,因为它被另一个进程使用。

我希望有道理!

对此的任何指导将非常感激,因为我相当坚持在哪里去与此。

+0

你可以使用一个库来为你做这件事,而不是重新创造你自己的。例如Log4net。 – Arran

回答

2

我有点困惑。为什么你将文件路径传递给记录器?它应该可能控制这个本身。就个人而言,我会做我的Logger类static,然后同步像这样的方法:

[MethodImpl(MethodImplOptions.Synchronized)] 
public static void Log(string description) 

然后,使用和作家内嵌的处置,以避免这些问题非常。

using (var writer = new StreamWriter(Path + "\\" + LOG_FILE, true)) 
{ 
    writer.WriteLine(log); 
    writer.Close(); 
} 
2

你的问题是,它是MT,最有可能你可能写入文件已经打开(比赛条件)

你为什么不使用一个单独为你的记录器/写入器?为什么不锁定作者,只使用一个实例而不是总是创建一个新的实例?

您的路径字符串看起来确实是错误的。我的意思是为什么要吐出文件名中的每个最后的毫秒/刻度?

我建议你使用单例方法进行日志记录,或者如果必须的话,创建记录器的静态实例并在完成时编写和处理时锁定文件。您正在写入可能正在使用的文件,而其他线程正在访问该文件。确保文件名也是唯一的 - 它可能不是你认为它在代码中。

+0

我可以通过示例代码使用单例。非常感谢! –

1

对于初学者DoProductStatsForCorporation记录器不应该是此函数的参数。 你的记录器应该在开始的时候创建,并且在课堂上成为一个领域。

您不想将记录器传递给函数,因为函数并不需要这个记录器来完成它的工作。

将记录器移出某些按钮代码,在构造函数中创建它,并使用类似于记录发生的类中的私有字段。

如果您想更改同一个类中的日志文件并记录到不同的文件,那么您必须重新编写记录器类,以便它可以使用多个文件。

另外,您可以了解有关Log4net的信息,这真的很不错。