同步线程访问和C#写入

我有一个用C#编写的multithreading端口扫描程序应用程序,我想在应用程序运行时将一些内容打印到控制台和日志文件。 出于这个原因,我有以下帮助器类,它可以很好地写入日志文件和控制台。

public class Output { private const string LOG_DIRECTORY = "Logs"; private readonly string LogDirPath = Path.Combine(Directory.GetCurrentDirectory(), LOG_DIRECTORY); private static Output _outputSingleton; private static Output OutputSingleton { get { if (_outputSingleton == null) { _outputSingleton = new Output(); } return _outputSingleton; } } public StreamWriter SW { get; set; } public Output() { EnsureLogDirectoryExists(); InstantiateStreamWriter(); } ~Output() { if (SW != null) { try { SW.Dispose(); } catch (ObjectDisposedException) { } // object already disposed - ignore exception } } public static void WriteLine(string str) { Console.WriteLine(str); OutputSingleton.SW.WriteLine(str); } public static void Write(string str) { Console.Write(str); OutputSingleton.SW.Write(str); } private void InstantiateStreamWriter() { long ticks = DateTime.Now.Ticks; string logFilename = "scan_" + ticks.ToString() + ".txt"; string filePath = Path.Combine(LogDirPath, logFilename); try { SW = new StreamWriter(filePath); SW.AutoFlush = true; } catch (UnauthorizedAccessException ex) { throw new ApplicationException(string.Format("Access denied. Could not instantiate StreamWriter using path: {0}.", filePath), ex); } } private void EnsureLogDirectoryExists() { if (!Directory.Exists(LogDirPath)) { try { Directory.CreateDirectory(LogDirPath); } catch (UnauthorizedAccessException ex) { throw new ApplicationException(string.Format("Access denied. Could not create log directory using path: {0}.", LogDirPath), ex); } } } } 

问题是,由于我的应用程序是multithreading的,有时我会创建多个日志文件,每个都部分写入,有时我会抛出exception,因为一个线程在被另一个线程使用时无法访问相同的位置。 有没有办法让我上面的Output类multithreading,以便我避免上述问题?

使用单个文件和lock策略应该完成这项工作:

 private Object m_Lock = new Object(); public static void WriteLine(string str) { lock (m_Lock) { Console.WriteLine(str); OutputSingleton.SW.WriteLine(str); } } public static void Write(string str) { lock (m_Lock) { Console.Write(str); OutputSingleton.SW.Write(str); } } private void InstantiateStreamWriter() { string logFilename = "Log.txt"; string filePath = Path.Combine(LogDirPath, logFilename); try { SW = new StreamWriter(filePath); SW.AutoFlush = true; } catch (UnauthorizedAccessException ex) { throw new ApplicationException(string.Format("Access denied. Could not instantiate StreamWriter using path: {0}.", filePath), ex); } } 

这里的问题是共享锁。 如果对多个方法使用相同的锁,则锁定一个方法也会锁定其他方法(在您的情况下为WriteWriteLine )。 它对我来说看起来完全没问题,因为它们是严格相关的…但如果频繁调用这些方法,这可能会造成瓶颈。 另一方面,单独的锁会使方法独立运行,这甚至更糟。

尝试将两个方法合并为一个,如下所示,因此您不必关心在单独的方法上处理锁:

 public static void WriteLine(String str, Boolean line = true) { lock (m_Lock) { if (line) { Console.WriteLine(str); OutputSingleton.SW.WriteLine(str); } else { Console.Write(str); OutputSingleton.SW.Write(str); } } }