现在有这样一个问题,请教各位大侠能否给个解决方案!
在form1 上面有两个用户控件 ,一个为A,一个为B,A控件启动了一个线程在以每5秒(也不是定时的)的速度在播放一个文件(类似幻灯片), B 控件也启动了一个线程在以一定时间(时间不定,5秒,10秒不等)在播放。
A控件和B控件都会写日志,比如A控件播放完一个文件,会把这个文件名称,播放的起始时间,播放完成时间,写到硬盘比如:D:\log.txt;B写日志我现在想到可能同时写一个文件会有问题,就存另外一个文件比如:d:\log2.txt;
现在目前的处理方式是,A和B 如果播放完成,就马上写日志,如果A是定时的,比如5秒播放一个文件,那就要5秒写一次文件,现在发现问题,是播放了一段时间后,有些日志没有写进去。请大家看下,这种方法是不是有问题。
另外,我想我是否可以在建立一个类,然后类里面建立一个静态的list,A 和 B比如播放完成,先把要写日志的数据存到list里面,然后 在form1里面启动一个进程,去监控这个list,如果这个list的数据量达到一定的大小,比如(1K),就写日志,然后清除list.不知道这种方法是否可行,需要注意那些问题,因为我听朋友说可以多线程操作静态成员好像会有问题
在form1 上面有两个用户控件 ,一个为A,一个为B,A控件启动了一个线程在以每5秒(也不是定时的)的速度在播放一个文件(类似幻灯片), B 控件也启动了一个线程在以一定时间(时间不定,5秒,10秒不等)在播放。
A控件和B控件都会写日志,比如A控件播放完一个文件,会把这个文件名称,播放的起始时间,播放完成时间,写到硬盘比如:D:\log.txt;B写日志我现在想到可能同时写一个文件会有问题,就存另外一个文件比如:d:\log2.txt;
现在目前的处理方式是,A和B 如果播放完成,就马上写日志,如果A是定时的,比如5秒播放一个文件,那就要5秒写一次文件,现在发现问题,是播放了一段时间后,有些日志没有写进去。请大家看下,这种方法是不是有问题。
另外,我想我是否可以在建立一个类,然后类里面建立一个静态的list,A 和 B比如播放完成,先把要写日志的数据存到list里面,然后 在form1里面启动一个进程,去监控这个list,如果这个list的数据量达到一定的大小,比如(1K),就写日志,然后清除list.不知道这种方法是否可行,需要注意那些问题,因为我听朋友说可以多线程操作静态成员好像会有问题
2. 你完全可以一个线程控制一个log.txt,两个文件可以避免多线程中不必要的麻烦!
3. 查询的时候可以将日志读到内存进行业务处理,在展示给客户看!
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
namespace Common
{
public static class WriteLog
{
static string FileName = "ErrorLog.txt";
const long MAXSIZE = 10 * 1024 * 1024;
static System.Object lockThis = new object();
public static void SetException(Exception exp)
{
SetException(exp, FileName);
} public static void SetException(Exception exp, string strFileName)
{
StringBuilder sb=new StringBuilder();
sb.AppendFormat("异常详细信息:{0}\r\n",exp.Message);
sb.AppendFormat("异常堆栈信息:{0}\r\n",exp.StackTrace);
if (strFileName == "")
strFileName = FileName;
SetString(sb.ToString(), strFileName);
}
public static void SetString(string str)
{
SetString(str, FileName);
} public static void SetString(string str, string strFileName)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("时间:{0}\r\n",System.DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss ffff"));
sb.Append(str+"\r\n");
sb.Append("---------------------------------------\r\n\r\n\r\n");
lock (lockThis)
{
StreamWriter w=null;
try
{
string fullFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strFileName);
FileInfo fileInfo = new FileInfo(fullFilePath);
if (fileInfo.Exists && fileInfo.Length > MAXSIZE)
{
fileInfo.Delete();
} w = new StreamWriter(fullFilePath, true, Encoding.GetEncoding("gb2312"));
w.Write(sb.ToString());
w.Flush();
}
catch
{
//not do }
finally
{
if (w != null)
{
try
{
w.Close();
w.Dispose();
}
catch
{
}
}
}
}
}
}
}
{
private static string m_LogDirPath = Application.StartupPath + @"\Logs";
private static string m_LogFile = string.Empty;
private static Worker m_Worker = new Worker();
private static object m_Lock = new object(); static WriteLogHelper()
{
if (Directory.Exists(m_LogDirPath) == false)
{
Directory.CreateDirectory(m_LogDirPath);
}
} #region 写出错信息
/// <summary>
/// 写出错信息
/// </summary>
/// <param name="strFuntiongName">
/// 简单说明
/// </param>
/// <param name="ex">
/// 异常
/// </param>
public static void WriteError(string msg, Exception ex)
{
lock (m_Lock)
{
m_Worker.WriteLogo(msg, ex);
}
} public static void WriteError(Exception ex)
{
lock (m_Lock)
{
string functionName = GetFunctionName();
m_Worker.WriteLogo(functionName + "出错。", ex);
}
} public static void WriteError(string msg)
{
lock (m_Lock)
{
m_Worker.WriteMessage(msg);
}
}
#endregion #region WriteDebug
[Conditional("DEBUG")]
public static void WriteDebug(Exception ex)
{
lock (m_Lock)
{
string functionName = GetFunctionName();
m_Worker.WriteLogo(functionName + "出错。", ex);
}
} [Conditional("DEBUG")]
public static void WriteDebug(string msg, Exception ex)
{
lock (m_Lock)
{
m_Worker.WriteLogo(msg, ex);
}
} [Conditional("DEBUG")]
public static void WriteDebug(string msg)
{
lock (m_Lock)
{
m_Worker.WriteMessage(msg);
}
}
#endregion public static string GetFunctionName()
{
try
{
StackTrace trace = new StackTrace(2);
if (trace.FrameCount <= 1)
{
return string.Empty;
}
MethodBase method = trace.GetFrame(0).GetMethod();
return string.Format("{0}.{1}", method.ReflectedType.FullName, method.Name);
}
catch { }
return string.Empty;
} private class Worker
{
int fileIndex = 0;
DateTime logTime = DateTime.Now;
string exFileName = ".log";
string baseFileName = m_LogDirPath + @"\" + Process.GetCurrentProcess().ProcessName + "." + DateTime.Now.ToString("yyyyMMdd"); public void WriteLogo(string msg, Exception ex)
{
FileIndexControl();
using (StreamWriter sw = File.AppendText(m_LogFile))
{
sw.Write(DateTime.Now);
sw.Write(" ");
sw.Write(msg);
sw.Write(" ");
sw.Write(ex.ToString());
sw.WriteLine();
}
} public void WriteMessage(string msg)
{
FileIndexControl();
using (StreamWriter sw = File.AppendText(m_LogFile))
{
sw.Write(DateTime.Now);
sw.Write(" ");
sw.WriteLine(msg);
} } private void FileIndexControl()
{ if (logTime.Date != DateTime.Now.Date)//另外一天
{
logTime = DateTime.Now;
fileIndex = 0;
baseFileName = m_LogDirPath + @"\" + Process.GetCurrentProcess().ProcessName + "." + DateTime.Now.ToString("yyyyMMdd");
m_LogFile = baseFileName + "_0" + exFileName;
}
else if (m_LogFile != string.Empty && File.Exists(m_LogFile))//
{
FileInfo fi = new FileInfo(m_LogFile);
if (fi.Length > 1024000)
{
fileIndex++;
m_LogFile = baseFileName + "_" + fileIndex.ToString() + exFileName;
}
}
else if (m_LogFile == string.Empty || m_LogFile.Length == 0)//logfile为空
{
m_LogFile = baseFileName + "_" + fileIndex.ToString() + exFileName;
}
}
}//worker
}
建立一个日志管理类,在该类中设置一个List<string>类型公有成员(命名为MessageList),然后在该类中建立一个方法(命名为MonitLogMessageList)单独开启一个线程负责监视这个成员,一旦其大小发生改变则将新内容写入日志文件中在调用者类的开始处就实例化日志管理类,然后调用MonitLogMessageList(),需要写日志时只需向日志管理类的MessageList中加入需要写入的日志文本字符串即可
按钮B播放,到调用线程写入日志的时候开一个线程写入,前提,写入的方法要加锁,
这样就能保证数据的准确性,当按钮A中的写入线程在执行写入的的时候,线程已经加锁,按钮B的写入线程是必须排队滴,要等到按钮A的写入线程操作完成,按钮B的写入线程才有资格去执行写入,按钮B的写入线程执行写入的时候,线程A同样也是要排队滴