我在使用Mutex进行线程同步时遇到此异常。我知道当我们没有以正确的方式在Mutex上调用ReleaseMutex时抛出此异常。但是在我的代码(下面)中,我试图记住代码,并牢牢记住这一点。我不知道在调用WaitOne()函数时引发异常的代码有什么问题。非常感谢您的帮助。
//Class File
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Configuration;
using System.Reflection;
using System.Xml;
using System.Diagnostics;
using System.Threading;
using System.Security.AccessControl;
namespace Utilities
{
public class EnvLogger : IDisposable
{
Mutex mutex = null;
int LineNumber = 0;
List<string> _Msgs;
//private String filePath;
private String logDirectory = "";
private StreamWriter sw;
private int logLevel;
private bool disposed = false;
private String strLogLevel;
private String Extension;
//constructor
/// <summary>
/// Use this constructor if File Name is Known.
/// </summary>
/// <param name="filename">Name of the file in which the contents would be put in</param>
/// <param name="assemblyName">Name of the folder in which the File will be created</param>
public EnvLogger(string filename, string assemblyName)
{
try
{
openMutex();
CreateFile(filename, assemblyName);
}
catch
{
return;
}
}
private void openMutex()
{
bool doesNotExist = false;
bool unauthorized = false;
string mutexName = "Log_Name";
// The value of this variable is set by the mutex
// constructor. It is true if the named system mutex was
// created, and false if the named mutex already existed.
//
bool mutexWasCreated = false;
// Attempt to open the named mutex.
try
{
// Open the mutex with (MutexRights.Synchronize |
// MutexRights.Modify), to enter and release the
// named mutex.
//
mutex = Mutex.OpenExisting(mutexName);
}
catch (WaitHandleCannotBeOpenedException)
{
doesNotExist = true;
}
catch (UnauthorizedAccessException)
{
unauthorized = true;
}
catch (Exception ex)
{
throw ex;
}
// There are three cases: (1) The mutex does not exist.
// (2) The mutex exists, but the current user doesn't
// have access. (3) The mutex exists and the user has
// access.
//
if (doesNotExist)
{
// The mutex does not exist, so create it.
// Create an access control list (ACL) that denies the
// current user the right to enter or release the
// mutex, but allows the right to read and change
// security information for the mutex.
//
string user = Environment.UserDomainName + "\\"
+ Environment.UserName;
MutexSecurity mSec = new MutexSecurity();
MutexAccessRule rule = new MutexAccessRule(user,
MutexRights.Synchronize | MutexRights.Modify,
AccessControlType.Deny);
mSec.AddAccessRule(rule);
rule = new MutexAccessRule(user,
MutexRights.ReadPermissions | MutexRights.ChangePermissions,
AccessControlType.Allow);
mSec.AddAccessRule(rule);
// Create a Mutex object that represents the system
// mutex named by the constant 'mutexName', with
// initial ownership for this thread, and with the
// specified security access. The Boolean value that
// indicates creation of the underlying system object
// is placed in mutexWasCreated.
//
mutex = new Mutex(true, mutexName, out mutexWasCreated, mSec);
// If the named system mutex was created, it can be
// used by the current instance of this program, even
// though the current user is denied access. The current
// program owns the mutex. Otherwise, exit the program.
//
if (!mutexWasCreated)
{
throw new Exception("Unable to create the mutex.");
}
}
else if (unauthorized)
{
// Open the mutex to read and change the access control
// security. The access control security defined above
// allows the current user to do this.
//
try
{
mutex = Mutex.OpenExisting(mutexName,
MutexRights.ReadPermissions | MutexRights.ChangePermissions);
// Get the current ACL. This requires
// MutexRights.ReadPermissions.
MutexSecurity mSec = mutex.GetAccessControl();
string user = Environment.UserDomainName + "\\"
+ Environment.UserName;
// First, the rule that denied the current user
// the right to enter and release the mutex must
// be removed.
MutexAccessRule rule = new MutexAccessRule(user,
MutexRights.Synchronize | MutexRights.Modify,
AccessControlType.Deny);
mSec.RemoveAccessRule(rule);
// Now grant the user the correct rights.
//
rule = new MutexAccessRule(user,
MutexRights.Synchronize | MutexRights.Modify,
AccessControlType.Allow);
mSec.AddAccessRule(rule);
// Update the ACL. This requires
// MutexRights.ChangePermissions.
mutex.SetAccessControl(mSec);
// Open the mutex with (MutexRights.Synchronize
// | MutexRights.Modify), the rights required to
// enter and release the mutex.
//
mutex = Mutex.OpenExisting(mutexName);
}
catch (UnauthorizedAccessException ex)
{
throw ex;
}
}
}
private Boolean CreateFile(string fileName, string assemblyName)
{
logLevel = (int)LogType.OFF; // _OFF;
try
{
logDirectory = GetAppConfig("logDirectory", ConfigArea.appSettings);
if (logDirectory == "OFF")
return false;
strLogLevel = GetAppConfig(assemblyName, ConfigArea.switches);
// System.Configuration.ConfigurationSettings.AppSettings["logging.level"].ToString();
Extension = GetAppConfig("DefaultLogFileExtension", ConfigArea.appSettings);
// System.Configuration.ConfigurationSettings.AppSettings["DefaultLogFileExtension"].ToString();
if (!Extension.Contains("."))
{
Extension = "." + Extension;
}
if (logLevel != (int)LogType.OFF)
{
_debugFolderPath = logDirectory + assemblyName + "\\" + DayOfWeek();
if (!Directory.Exists(_debugFolderPath))
{
Directory.CreateDirectory(_debugFolderPath);
}
String filePath = _debugFolderPath + "\\" + fileName;
//****** BEGIN FIX FIXLOGFAIL ******
FileInfo info = new FileInfo(filePath);
string Ext = info.Extension;
if (!((Ext == ".log") || (Ext == ".txt")))
filePath = filePath + ".log";
//****** end FIX FIXLOGFAIL ******
FilePath = filePath;
if (!File.Exists(FilePath))
{
FileStream fs = File.Create(FilePath);
fs.Close();
fs.Dispose();
}
}
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Appending text to files
/// </summary>
/// <param name="message">Message to be Added</param>
public void AppendToFile(String message)
{
if (mutex.WaitOne()) // exception thown at this
{
try
{
sw = File.AppendText(FilePath);
if (level == LogType.ERROR)
sw.Write("Error: ");
else if (level == LogType.WARN)
sw.Write("Warning: ");
string strLinesmsg = LineNumber.ToString("000000");
strLinesmsg = strLinesmsg + " " + DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + " " + message;
sw.WriteLine(strLinesmsg);
LineNumber++;
if (LineNumber >= 99999)
LineNumber = 0;
//sw.WriteLine("");
sw.Flush();
sw.Close();
}
catch (Exception ex)
{
WriteToEventLog(ex.Message);
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
}
//Client Code
private void btnLogger_Click(object sender, EventArgs e)
{
EnvLogger ObjLog = null;
string m_LogFile = "LogFileName";
m_LogFile += DateTime.Now.ToString("yyyy-MMM-dd-HH-mm-ss-fff") + Guid.NewGuid().ToString().Substring(0, 8);
ObjLog = new EnvLogger(m_LogFile, "AssemblyName.dll"); // Error comes at this
ObjLog.AppendToFile(" Debuging the Assembly : AssemblyName started at : " + DateTime.Now.ToString());
ObjLog.AppendToFile("Inside the SendDatatoProcess function");
}