请问,如何解决多线程访问同一个文件句柄、资源的冲突问题?谢谢!比如:如下类,是用于记录程序日志的。我调用共用的Log方法来记录程序中的任何日志。这在单线程的应用中没有任何问题。
但是,在多线程的调用中,也就是几个不同的线程同时对LogHelpers进行Log方法调用时,sw对象会出现error。看上去像是一个线程正在对文件写操作时,另一个线程已经把sw对象给关闭了。所以,有的时候,这一句报错。
sw.WriteLine(Line, arg);MSG: Cannot write to a closed TextWriter.
STACK: at System.IO.__Error.WriterClosed()
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Write(Char[] buffer, Int32 index, Int32 count)
at System.IO.TextWriter.WriteLine(String value)
at System.IO.TextWriter.WriteLine(String format, Object[] arg)
Type: System.ObjectDisposedException
THROWN BY: Void WriterClosed()
请问,如何修改这个类的代码,来避免这种情况?
要求,每调用一次Log方法,必须1)打开文件;2)写文件;3)关闭文件;这个不能变。
另外,不同的线程对这个类的Log方法调用顺序,时间,频率是不可知的。请问,C#,有没有简单的锁保护机制(语句)可以用于解决这种冲突?请提供示例代码,谢谢!用lock语句可以解决吗?
lock (syncRoot)
{
}
下面是用于记录程序日志的类Class LogHelpers
{
private static StreamWriter sw;
private static string fileName="c:\testlogs.log";
private static long maxFileSize=65535;
protected static void WriteLine(string Line, params object[] arg)
{
try
{
// Write to log
if (sw != null) sw.WriteLine(Line, arg);
}
catch (System.ObjectDisposedException ex)
{
OpenLogFile();
// Write to log
if (sw != null) sw.WriteLine(Line, arg); } } private static void OpenLogFile()
{
try
{
if (sw != null)
sw.Close();
fi = new FileInfo(fileName);
if (!fi.Directory.Exists)
Directory.CreateDirectory(fi.DirectoryName);
if (fi.Exists && fi.Length < maxFileSize)
if (encrypted)
sw = CreateEncrypted(FileMode.Append);
else
sw = File.AppendText(fileName); // Append to the file.
else if (encrypted)
sw = CreateEncrypted(FileMode.Create);
else
sw = File.CreateText(fileName); // Clears the log. // TODO Autoflush?
// We have to use Autoflash for calculating the file size
// in current implementation, see BeginLog
sw.AutoFlush = true;
}
catch
{
//do nothing.
}
} protected static void BeginLog()
{
if (sw == null)
OpenLogFile(); fi = new FileInfo(fileName);
if (fi.Length > maxFileSize)
{
// rename file to .prev:
string prev = fileName + ".prev";
if (File.Exists(prev))
File.Delete(prev); sw.Close();
fi.MoveTo(prev); // reopen new file:
OpenLogFile();
}
} protected static void EndLog()
{
if (sw != null)
{
//TODO: keep open? close? use a pool of writers?
sw.Close();
sw = null;
}
} public static void Log(string str)
{
BeginLog(); WriteLine("* * * * * * * * * * * *");
WriteLine(String.Format("{0, -13}", "DATE & TIME: ") +
DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss:ff tt"));
WriteLine(str);
WriteLine(""); EndLog();
}
}
但是,在多线程的调用中,也就是几个不同的线程同时对LogHelpers进行Log方法调用时,sw对象会出现error。看上去像是一个线程正在对文件写操作时,另一个线程已经把sw对象给关闭了。所以,有的时候,这一句报错。
sw.WriteLine(Line, arg);MSG: Cannot write to a closed TextWriter.
STACK: at System.IO.__Error.WriterClosed()
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Write(Char[] buffer, Int32 index, Int32 count)
at System.IO.TextWriter.WriteLine(String value)
at System.IO.TextWriter.WriteLine(String format, Object[] arg)
Type: System.ObjectDisposedException
THROWN BY: Void WriterClosed()
请问,如何修改这个类的代码,来避免这种情况?
要求,每调用一次Log方法,必须1)打开文件;2)写文件;3)关闭文件;这个不能变。
另外,不同的线程对这个类的Log方法调用顺序,时间,频率是不可知的。请问,C#,有没有简单的锁保护机制(语句)可以用于解决这种冲突?请提供示例代码,谢谢!用lock语句可以解决吗?
lock (syncRoot)
{
}
下面是用于记录程序日志的类Class LogHelpers
{
private static StreamWriter sw;
private static string fileName="c:\testlogs.log";
private static long maxFileSize=65535;
protected static void WriteLine(string Line, params object[] arg)
{
try
{
// Write to log
if (sw != null) sw.WriteLine(Line, arg);
}
catch (System.ObjectDisposedException ex)
{
OpenLogFile();
// Write to log
if (sw != null) sw.WriteLine(Line, arg); } } private static void OpenLogFile()
{
try
{
if (sw != null)
sw.Close();
fi = new FileInfo(fileName);
if (!fi.Directory.Exists)
Directory.CreateDirectory(fi.DirectoryName);
if (fi.Exists && fi.Length < maxFileSize)
if (encrypted)
sw = CreateEncrypted(FileMode.Append);
else
sw = File.AppendText(fileName); // Append to the file.
else if (encrypted)
sw = CreateEncrypted(FileMode.Create);
else
sw = File.CreateText(fileName); // Clears the log. // TODO Autoflush?
// We have to use Autoflash for calculating the file size
// in current implementation, see BeginLog
sw.AutoFlush = true;
}
catch
{
//do nothing.
}
} protected static void BeginLog()
{
if (sw == null)
OpenLogFile(); fi = new FileInfo(fileName);
if (fi.Length > maxFileSize)
{
// rename file to .prev:
string prev = fileName + ".prev";
if (File.Exists(prev))
File.Delete(prev); sw.Close();
fi.MoveTo(prev); // reopen new file:
OpenLogFile();
}
} protected static void EndLog()
{
if (sw != null)
{
//TODO: keep open? close? use a pool of writers?
sw.Close();
sw = null;
}
} public static void Log(string str)
{
BeginLog(); WriteLine("* * * * * * * * * * * *");
WriteLine(String.Format("{0, -13}", "DATE & TIME: ") +
DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss:ff tt"));
WriteLine(str);
WriteLine(""); EndLog();
}
}
解决方案 »
- 这题真不会做~望高手指点!谢谢!
- vs2008打包web 程序 并建立桌面快捷方式
- dll控件里函数中LPSTR这样的参数类型应该在C#里如何调用。
- 想做个类似QQ界面的程序,找不到SideBar.dll
- 如果我说C#比不上VB.Net,肯定有人向我拍砖
- 请问树的节点展开问题,很简单,来拿分
- 请教,word中的图片如何保存出来?
- 怎么在aspx里面的javascript中调用cs中变量的值
- 用winform自带的打包软件可以编写卸载程序吗?
- 谁有用DES加密解密的代码?C#的。
- C#图像处理,速度太慢了,大家近来看看,帮帮小弟。。。。。。。。。。。。。。。。。。。。。。。
- Socket的问题,关于StateObject
public static void Log(string str)
{
Lock (syncRoot)
{
BeginLog(); WriteLine("* * * * * * * * * * * *");
WriteLine(String.Format("{0, -13}", "DATE & TIME: ") +
DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss:ff tt"));
WriteLine(str);
WriteLine(""); EndLog();
}
}
public static void Log(string str)
{
Lock (sw)
{
BeginLog(); WriteLine("* * * * * * * * * * * *");
WriteLine(String.Format("{0, -13}", "DATE & TIME: ") +
DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss:ff tt"));
WriteLine(str);
WriteLine(""); EndLog();
}
}
你可以在程序的开头指定log到一个文件: TextWriterTraceListener logWriter = new TextWriterTraceListener( @"c:\temp\log.txt" );
Trace.Listeners.Add( logWriter );
也可以事后在程序的配置文件中进行配置(见System.Diagnostics.Trace类)写日志更简单: Trace.TraceWarning("Cannot open file: {0}", "abc.txt");
ReaderWriterLock RWL = new ReaderWriterLock();
RWL.AcquireWriterLock(1000);
在.NET里面用EventLog对象来访问,很方便