这是我最近一次运行的输出,其中我并行索引数据库表的10列。写入日志文件的代码如下。
INFO: Status Indexing column Master_State as index I5
INFO: Status Indexing column Master_current0 as index I4
INFO: Status Indexing column Master_qlevel as index I3
INFO: Status Indexing column Master_received_Day as index I1
Got sharing exception with lock!
INFO: Status Indexing column Master_customer as index I7
Waiting on file
INFO: Status Indexing column Master_received_Year as index I8
INFO: Status Indexing column Master_received_Month as index I9
Waiting on file
INFO: Status Indexing column seq_no as index I10
这里是编写消息“带锁的共享异常!”的代码。
private static void WriteToPath(object msg, string logPath)
{
while (true)
{
try
{ // These first two lines are to handle different users and/or
// applications that log to the same log file.
// If the File.Open fails because the file is in use, Exception
// then wait and try again.
//
FileStream writer = File.Open(logPath, FileMode.Append);
writer.Close();
locker.AcquireWriterLock(writerTimeouts);
try
{
Interlocked.Increment(ref writes);
try
{
using (var logWriter = File.AppendText(logPath))
{
logWriter.WriteLine((string)msg);
}
break; // break out of the while loop as we're done.
}
catch
{ // Here I write out the fact that I got an exception
// but not the long details about file sharing exception.
Console.Out.WriteLine("Got sharing exception with lock!");
}
}
finally
{
if (locker.IsWriterLockHeld)
locker.ReleaseWriterLock();
}
}
catch (Exception)
{
Interlocked.Increment(ref writerTimeouts);
Console.Out.WriteLine("Waiting on file");
Thread.Sleep(5000);
}
}
}
此WriteToPath的调用如下所示:
public static void Log(string dir, string pgm, string errorLevel, string msgType, string details)
{
string line = null;
if (details != null)
{
line = FormatLogMessage(pgm, errorLevel, msgType, details);
}
else
{
line = FormatLogMessage(pgm, "INFO", "End", BuildInfo.ApplicationName);
}
ThreadPool.QueueUserWorkItem(WriteWithLock, line);
}
private static void WriteWithLock(object msg)
{
string logPath = _cfg.getLogDirectory() + GetLogFileName();
WriteToPath(msg, logPath);
}
这是使用
并行运行的一系列应用程序的一部分 ProcessStartInfo info = new ProcessStartInfo();
info.FileName = batchFile;
info.Arguments = argList;
Process.Start(info);
因此,每个应用程序都独立运行。因此,它们没有共享或通用锁,但每个应用程序都有一个。这些应用程序通常运行大约10个线程,所有线程都在执行类似的工作,例如为数据库的列建立索引,或将来自10个不同文件的行插入数据库等。对于这些应用程序,上述锁定机制应该起作用。但是,我开始等待存档,有时会遇到“共享异常”。它对并行线程有效,并且我不会丢失任何数据,但是为什么会发生呢?另外,这对单独的应用程序有用吗?
似乎Windows 10应该具有类似 任何人都可以调用的System.Logging.LogToFile(path,message),系统将管理任何冲突。我找不到这样的东西,但是肯定会很好!
在此方面的协助将不胜感激。
答案 0 :(得分:0)
这里是我所用的精简版本,互斥体应该做您想要的事情,至少这对我没有问题:
public sealed class GlobalLogger : IDisposable
{
private static GlobalLogger Logger;
private readonly Mutex _lock;
private string _activityLogPath;
private const string ActivityLogFileName = @"activity.log";
private GlobalLogger()
{
_lock = new Mutex(false, ActivityLogFileName);
}
/// <summary> Finds the root path of the MSD, sets up log file. </summary>
/// <returns>Drive info, or null if not found</returns>
public static void Init()
{
if (null == Logger)
{
Logger = new GlobalLogger();
}
if (string.IsNullOrEmpty(_activityLogPath))
{
Logger._activityLogPath = ActivityLogFileName;
}
}
//
// Debug
//
public static void DebugWriteLineInfo(object sender, string format, params object[] args)
{
DebugWriteMessage(sender, "I", true, format, args);
}
public static void DebugWriteLineWarning(object sender, string format, params object[] args)
{
DebugWriteMessage(sender, "W", true, format, args);
}
public static void DebugWriteLineError(object sender, string format, params object[] args)
{
DebugWriteMessage(sender, "E", true, format, args);
}
private static void DebugWriteMessage(object sender, string severity, bool writeLine, string format, params object[] args)
{
if (writeLine)
{
Debug.WriteLine(format);
}
else
{
Debug.Write(format);
}
}
//
// Logging
//
private static void Log(string logType, string severity, object sender, string format, params object[] args)
{
Init();
if (Logger._lock.WaitOne(250))
{
try
{
using (StreamWriter sw = new StreamWriter(Logger._activityLogPath, true))
{
if (logType != "RAW")
{
sw.Write("{0} {1} {2} ",
DateTime.Now,
logType,
severity);
}
sw.WriteLine(format, args);
}
}
finally
{
Logger._lock.ReleaseMutex();
}
}
}
public static void LogActivityInformation(object sender, string format, params object[] args)
{
Log("ACT", "I", sender, format, args);
}
public static void LogActivityWarning(object sender, string format, params object[] args)
{
Log("ACT", "W", sender, format, args);
}
public static void LogActivityError(object sender, string format, params object[] args)
{
Log("ACT", "E", sender, format, args);
}
public static void LogApplicationInformation(object sender, string format, params object[] args)
{
Log("APP", "I", sender, format, args);
}
public static void LogApplicationWarning(object sender, string format, params object[] args)
{
Log("APP", "W", sender, format, args);
}
public static void LogApplicationError(object sender, string format, params object[] args)
{
Log("APP", "E", sender, format, args);
}
public static void LogSystemInformation(object sender, string format, params object[] args)
{
Log("SYS", "I", sender, format, args);
}
public static void LogSystemWarning(object sender, string format, params object[] args)
{
Log("SYS", "W", sender, format, args);
}
public static void LogSystemError(object sender, string format, params object[] args)
{
Log("SYS", "E", sender, format, args);
}
public static void LogRaw(object sender, string format, params object[] args)
{
Log("RAW", string.Empty, sender, format, args);
}
public void Dispose()
{
if (null != _lock)
{
_lock.Close();
}
}
}
大多数时候我只是这样记录:GlobalLogger.LogApplicationInformation(this,“信息消息:{0}”,randomTypeArg);