System.Threading.AbandonedMutexException:由于废弃的互斥锁而导致等待完成?

时间:2011-02-28 09:21:37

标签: c# .net multithreading c#-3.0

我在使用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");
}

0 个答案:

没有答案