码迷,mamicode.com
首页 > Windows程序 > 详细

C# 多进程安全

时间:2019-03-01 12:15:25      阅读:344      评论:0      收藏:0      [点我收藏+]

标签:一个   base64   控制   final   data   encoding   互斥量   catch   示例   

多个应用程序同时写入数据到一个文件中时可用

            public void WriteData(string dataWh, string filePath)
            {
                EventWaitHandle waitHandle = new EventWaitHandle(true, EventResetMode.AutoReset, "SHARED_BY_ALL_PROCESSES");
                waitHandle.WaitOne();
                try
                {
                    using (var fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        byte[] dataAsByteArray = new UTF8Encoding(true).GetBytes(dataWh);
                        fs.Write(dataAsByteArray, 0, dataWh.Length);
                        Console.WriteLine("111111111111");
                    }
                }
                finally
                {
                    waitHandle.Set();
                }
            }
SHARED_BY_ALL_PROCESSES 是字符串键
确保所有应用程序中的键是一样的值, try里面的代码就是进程安全的.

可以复制这这段代码新建两个控制台程序试试 ^ ^


进阶补充(抄) 加入异常, 生成键值的方法
    /// <summary>
    /// C#互斥量使用示例代码
    /// </summary>
    static class MutexHelper
    {
        /// <summary>
        /// 获取文件名对应的进程同步键
        /// </summary>
        /// <param name="filePath">文件路径(请注意大小写及空格)</param>
        /// <returns>进程同步键(互斥体名称)</returns>
        public static string GetFilePathMutexKey(string filePath)
        {
            //生成文件对应的同步键,可自定义格式(互斥体名称对特殊字符支持不友好,遂转换为BASE64格式字符串)
            var fileKey = Convert.ToBase64String(Encoding.Default.GetBytes(string.Format(@"FILE\{0}", filePath)));
            //转换为操作系统级的同步键
            var mutexKey = string.Format(@"Global\{0}", fileKey);
            return mutexKey;
        }

        /// <summary>
        /// 进程间同步执行
        /// </summary>
        /// <param name="mutexKey">操作系统级的同步键
        /// (如果将 name 指定为 null 或空字符串,则创建一个局部互斥体。 
        /// 如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。 
        /// 如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。 
        /// 如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。)</param>
        /// <param name="action">同步处理操作</param>
        public static void MutexExec(string mutexKey, Action action)
        {
            MutexExec(mutexKey: mutexKey, action: action, recursive: false);
        }

        /// <summary>
        /// 进程间同步执行
        /// </summary>
        /// <param name="mutexKey">操作系统级的同步键
        /// (如果将 name 指定为 null 或空字符串,则创建一个局部互斥体。 
        /// 如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。 
        /// 如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。 
        /// 如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。)</param>
        /// <param name="action">同步处理操作</param>
        /// <param name="recursive">指示当前调用是否为递归处理,递归处理时检测到异常则抛出异常,避免进入无限递归</param>
        private static void MutexExec(string mutexKey, Action action, bool recursive)
        {
            //声明一个已命名的互斥体,实现进程间同步;该命名互斥体不存在则自动创建,已存在则直接获取
            //initiallyOwned: false:默认当前线程并不拥有已存在互斥体的所属权,即默认本线程并非为首次创建该命名互斥体的线程
            //注意:并发声明同名的命名互斥体时,若间隔时间过短,则可能同时声明了多个名称相同的互斥体,并且同名的多个互斥体之间并不同步,高并发用户请另行处理
            using (Mutex mut = new Mutex(initiallyOwned: false, name: mutexKey))
            {
                try
                {
                    //上锁,其他线程需等待释放锁之后才能执行处理;若其他线程已经上锁或优先上锁,则先等待其他线程执行完毕
                    mut.WaitOne();
                    //执行处理代码(在调用WaitHandle.WaitOne至WaitHandle.ReleaseMutex的时间段里,只有一个线程处理,其他线程都得等待释放锁后才能执行该代码段)
                    action();
                }
                //当其他进程已上锁且没有正常释放互斥锁时(譬如进程忽然关闭或退出),则会抛出AbandonedMutexException异常
                catch (AbandonedMutexException ex)
                {
                    //避免进入无限递归
                    if (recursive)
                        throw new Exception("避免进入无限递归", ex);

                    //非递归调用,由其他进程抛出互斥锁解锁异常时,重试执行
                    MutexExec(mutexKey: mutexKey, action: action, recursive: true);
                }
                finally
                {
                    //释放锁,让其他进程(或线程)得以继续执行
                    mut.ReleaseMutex();
                }
            }
        }
    }

 

    /// <summary>    /// C#互斥量使用示例代码    /// </summary>    static class MutexHelper    {        /// <summary>        /// 获取文件名对应的进程同步键        /// </summary>        /// <param name="filePath">文件路径(请注意大小写及空格)</param>        /// <returns>进程同步键(互斥体名称)</returns>        public static string GetFilePathMutexKey(string filePath)        {            //生成文件对应的同步键,可自定义格式(互斥体名称对特殊字符支持不友好,遂转换为BASE64格式字符串)            var fileKey = Convert.ToBase64String(Encoding.Default.GetBytes(string.Format(@"FILE\{0}", filePath)));            //转换为操作系统级的同步键            var mutexKey = string.Format(@"Global\{0}", fileKey);            return mutexKey;        }
        /// <summary>        /// 进程间同步执行        /// </summary>        /// <param name="mutexKey">操作系统级的同步键        /// (如果将 name 指定为 null 或空字符串,则创建一个局部互斥体。         /// 如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。         /// 如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。         /// 如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。)</param>        /// <param name="action">同步处理操作</param>        public static void MutexExec(string mutexKey, Action action)        {            MutexExec(mutexKey: mutexKey, action: action, recursive: false);        }
        /// <summary>        /// 进程间同步执行        /// </summary>        /// <param name="mutexKey">操作系统级的同步键        /// (如果将 name 指定为 null 或空字符串,则创建一个局部互斥体。         /// 如果名称以前缀“Global\”开头,则 mutex 在所有终端服务器会话中均为可见。         /// 如果名称以前缀“Local\”开头,则 mutex 仅在创建它的终端服务器会话中可见。         /// 如果创建已命名 mutex 时不指定前缀,则它将采用前缀“Local\”。)</param>        /// <param name="action">同步处理操作</param>        /// <param name="recursive">指示当前调用是否为递归处理,递归处理时检测到异常则抛出异常,避免进入无限递归</param>        private static void MutexExec(string mutexKey, Action action, bool recursive)        {            //声明一个已命名的互斥体,实现进程间同步;该命名互斥体不存在则自动创建,已存在则直接获取            //initiallyOwned: false:默认当前线程并不拥有已存在互斥体的所属权,即默认本线程并非为首次创建该命名互斥体的线程            //注意:并发声明同名的命名互斥体时,若间隔时间过短,则可能同时声明了多个名称相同的互斥体,并且同名的多个互斥体之间并不同步,高并发用户请另行处理            using (Mutex mut = new Mutex(initiallyOwned: false, name: mutexKey))            {                try                {                    //上锁,其他线程需等待释放锁之后才能执行处理;若其他线程已经上锁或优先上锁,则先等待其他线程执行完毕                    mut.WaitOne();                    //执行处理代码(在调用WaitHandle.WaitOne至WaitHandle.ReleaseMutex的时间段里,只有一个线程处理,其他线程都得等待释放锁后才能执行该代码段)                    action();                }                //当其他进程已上锁且没有正常释放互斥锁时(譬如进程忽然关闭或退出),则会抛出AbandonedMutexException异常                catch (AbandonedMutexException ex)                {                    //避免进入无限递归                    if (recursive)                        throw new Exception("避免进入无限递归", ex);
                    //非递归调用,由其他进程抛出互斥锁解锁异常时,重试执行                    MutexExec(mutexKey: mutexKey, action: action, recursive: true);                }                finally                {                    //释放锁,让其他进程(或线程)得以继续执行                    mut.ReleaseMutex();                }            }        }    }

 

C# 多进程安全

标签:一个   base64   控制   final   data   encoding   互斥量   catch   示例   

原文地址:https://www.cnblogs.com/nocanstillbb/p/10455542.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!