在我们的WebService中有下面一个方法,用于在service访问中如果发生异常时,记录此异常所用!
由于有很多系统都在调用此web service,也就是说对此log.txt的访问实际为并发操作。这也就存在一个并发控制的问题:
由于有很多系统都在调用此web service,也就是说对此log.txt的访问实际为并发操作。这也就存在一个并发控制的问题:
protected
void
writeLog(
string
detailDesc)
{
Monitor.Enter(lockObject);
System.IO.StreamWriter sw = null ;
try
{
string logFile = Server.MapPath( " ~/Log/ " + this .GetType().Name + " .txt " );
string fullText = DateTime.Now.ToString( " yyyy/MM/dd HH:mm:ss " ) + " \t " + HttpContext.Current.Request.UserHostAddress + " \t " + detailDesc;
checkFile(logFile);
sw = System.IO.File.AppendText(logFile);
sw.WriteLine(fullText);
sw.Flush();
}
finally
{
Monitor.Exit(lockObject);
sw.Close();
}
}
{
Monitor.Enter(lockObject);
System.IO.StreamWriter sw = null ;
try
{
string logFile = Server.MapPath( " ~/Log/ " + this .GetType().Name + " .txt " );
string fullText = DateTime.Now.ToString( " yyyy/MM/dd HH:mm:ss " ) + " \t " + HttpContext.Current.Request.UserHostAddress + " \t " + detailDesc;
checkFile(logFile);
sw = System.IO.File.AppendText(logFile);
sw.WriteLine(fullText);
sw.Flush();
}
finally
{
Monitor.Exit(lockObject);
sw.Close();
}
}
在多线程的环境中为了避免同一时间有多线程同时执行写档的程序而造成例外状况。
理论上看似不会出问题的程序跑到catch的区段?错误信息如下:
The process cannot access the file 'D:\log_20100630.txt' because it is being used by another process.
到底出了什么问题?另外msdn中查到
請使用 Enter,來取得當做參數傳遞之物件上的 Monitor。如果有其他執行緒已在物件上執行過 Enter,但還沒有執行對應的 Exit,目前的執行緒會阻斷,直到另一執行緒釋出物件為止。同一個執行緒叫用 Enter 不只一次而不發生封鎖是合法的情形;不過,必須先叫用等數量的 Exit 呼叫,等候物件的其他執行緒才會解除封鎖。
问题很简单,sw.Close()放在了 Monitor.Exit(lockObject);之后。我们知道 Monitor.Exit(lockObject)用于unlock锁定的对象,使得程序可被进入。而sw.Close()用于释放sw资源,关闭txt文本,使得下一个process可以打开并访问。而如果按照现在的执行逻辑就可能造成:unlock对象后,在释放sw资源资源之前就有另一个process进入访问,必然出错。故而应先释放资源,而后Unlock才可保证并发操作正常进行。
<