• C# 线程同步之Moitor实现线程的顺序执行


    有这么个场景,A线程执行A函数,B线程执行B函数,C线程执行C函数,并且ABC函数要按顺序执行,如何实现

    我们可以利用Monitor和ConcurrentDictionary来实现。

    Monitor是比lock更灵活操作,再.net中,lock在中间语言会被翻译成Monitor;

    ConcurrentDictionary是线程安全的字典。

    实现一个类:

       /// <summary>
        /// 顺序线程 线程按执行顺序
        /// </summary>
        public class OrderedThread
        {
            #region 静态字段
    
            /// <summary>
            /// 当前的线程循序序号
            /// </summary>
            private static int _inner_orderedID = 0;
    
            /// <summary>
            /// 当前的线程的队列
            /// </summary>
            private static ConcurrentDictionary<int, OrderedThread> inner_readyThreadList = new ConcurrentDictionary<int, OrderedThread>();
    
            /// <summary>
            /// 线程锁
            /// </summary>
            private static object _objLock = new object();
    
            #endregion
    
            #region 成员字段
    
            /// <summary>
            /// 处理的委托
            /// </summary>
            private Action<int> _inner_action = null;
    
            #endregion
    
            #region 构造函数
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="handling">处理的委托</param>
            public OrderedThread(Action<int> handling)
            {
                this._inner_action = handling;
            }
    
            #endregion
    
            #region 开始执行线程
    
            /// <summary>
            /// 开始执行线程
            /// </summary>
            public void Start()
            {
                //添加到就绪集合中
                inner_readyThreadList.AddOrUpdate(_inner_orderedID++, this, (key, vlaue) =>
                {
                    return this;
                });
    
                Thread th = new Thread(() =>
                {
                    bool isEnter = Monitor.TryEnter(_objLock);
                    if (isEnter)
                    {
                        //如果就绪队列中有要执行的线程
                        while (inner_readyThreadList.Count() > 0)
                        {
                            //找到起始的最小值
                            int minIndex = inner_readyThreadList.Keys.Min();
    
                            //绪队列中线程执行
                            inner_readyThreadList[minIndex]._inner_action.Invoke(minIndex);
    
                            //移除执行完成的
                            OrderedThread orderedThreadTmp = null;
                            inner_readyThreadList.TryRemove(minIndex, out orderedThreadTmp);
                        }
    
                        Monitor.Exit(_objLock);
                    }
                });
                th.SetApartmentState(ApartmentState.STA);
                th.IsBackground = true;
                th.Start();
            }
    
            #endregion
        }

    我们的业务类:

        public class PrintClass 
        {
            public void PrintOne() 
            {
                Console.WriteLine("one");
            }
    
            public void PrintTwo()
            {
                Console.WriteLine("two");
            }
    
            public void PrintThree()
            {
                Console.WriteLine("three");
            }
    
        }

    调用:

     class Program
        {
            static void Main(string[] args)
            {
                PrintClass p=new PrintClass();
    
                OrderedThread firstThread = new OrderedThread((o)=> {
                    p.PrintOne();
                    Thread.Sleep(5000);
                });
    
                OrderedThread SecondThread = new OrderedThread((o) => {
                    p.PrintTwo();
    
                });
    
                OrderedThread ThirdThread = new OrderedThread((o) => {
                    p.PrintThree();
    
                });
    
                firstThread.Start();
                ThirdThread.Start();
    
                SecondThread.Start();
    
    
    
                Console.ReadLine();
            }
        }

    其中:Start的顺序就是要执行的顺序。

  • 相关阅读:
    Delphi下Treeview控件基于节点编号的访问
    oracle的conn / as sysdba是以sys还是system用户登录呢?
    delphi 字母加数字如何自增??比如0A--0Z,1A--1Z一直到9A--9Z 请赐教
    ORACLE_HOME要怎么配置?
    sqlplus / as sysdba 详解
    oracle 11G数据库实例增加内存
    SQL在字符串中取出最长数字子序列
    delphi 全局变量的定义与初始化赋值
    Delphi公用函数单元
    Dapper的正确使用姿势
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/13540055.html
Copyright © 2020-2023  润新知