• [.NET] STAThread


    在WindowForm应用程序中主要的线程,是采用一种称为「Single-Threaded Apartment(STA)」的线程模型。这个STA线程模型,在线程内加入了讯息帮浦等等机制,减少开发人员撰写窗口程序的工作量。相关的信息可以参考:[Object-oriented] 线程

    而在开发类别库的时候,如果要使用类似的STA线程模型,可以使用下列的程序代码提供的类别来完成。

    namespace CLK.Threading
    {
        public class STAThread
        {
            // Enum
            private enum ThreadState
            {
                Started,
                Stopping,
                Stopped,
            }
    
    
            // Fields
            private readonly object _syncRoot = new object();
    
            private readonly BlockingQueue<Action> _actionQueue = null;
    
            private Thread _thread = null;
    
            private ManualResetEvent _threadEvent = null;
    
            private ThreadState _threadState = ThreadState.Stopped;       
    
    
            // Constructor
            public STAThread()
            {
                // ActionQueue
                _actionQueue = new BlockingQueue<Action>();
                            
                // ThreadEvent
                _threadEvent = new ManualResetEvent(true);
    
                // ThreadState
                _threadState = ThreadState.Stopped;       
            }
    
    
            // Methods
            public void Start()
            {            
                // Sync
                lock (_syncRoot)
                {
                    // ThreadState
                    if (_threadState != ThreadState.Stopped) throw new InvalidOperationException();
                    _threadState = ThreadState.Started;
                }
    
                // Thread
                _thread = new Thread(this.Operate);
                _thread.Name = string.Format("Class:{0}, Id:{1}", "STAThread", _thread.ManagedThreadId);
                _thread.IsBackground = false;
                _thread.Start();
            }
    
            public void Stop()
            {
                // Sync
                lock (_syncRoot)
                {
                    // ThreadState
                    if (_threadState != ThreadState.Started) throw new InvalidOperationException();
                    _threadState = ThreadState.Stopping;
    
                    // ActionQueue
                    _actionQueue.Release();
                }
    
                // Wait
                _threadEvent.WaitOne();
            }
    
    
            public void Post(SendOrPostCallback callback, object state)
            {
                #region Contracts
    
                if (callback == null) throw new ArgumentNullException();
    
                #endregion
                
                // Action
                Action action = delegate()
                {
                    try
                    {
                        callback(state);
                    }
                    catch (Exception ex)
                    {
                        Debug.Fail(string.Format("Delegate:{0}, State:{1}, Message:{2}", callback.GetType(), "Exception", ex.Message));
                    }
                };
    
                // Sync
                lock (_syncRoot)
                {
                    // ThreadState
                    if (_threadState != ThreadState.Started) throw new InvalidOperationException();
    
                    // ActionQueue
                    _actionQueue.Enqueue(action);
                }                       
            }
    
            public void Send(SendOrPostCallback callback, object state)
            {
                #region Contracts
    
                if (callback == null) throw new ArgumentNullException();
    
                #endregion
    
                // Action 
                ManualResetEvent actionEvent = new ManualResetEvent(false);
                Action action = delegate()
                {
                    try
                    {
                        callback(state);
                    }
                    catch (Exception ex)
                    {
                        Debug.Fail(string.Format("Delegate:{0}, State:{1}, Message:{2}", callback.GetType(), "Exception", ex.Message));
                    }
                    finally
                    {
                        actionEvent.Set();
                    }
                };
    
                // Sync
                lock (_syncRoot)
                {
                    // ThreadState
                    if (_threadState != ThreadState.Started) throw new InvalidOperationException();
    
                    // ActionQueue
                    if (Thread.CurrentThread != _thread)
                    {
                        _actionQueue.Enqueue(action);
                    }
                }
    
                // Execute
                if (Thread.CurrentThread == _thread)
                {
                    action();
                }
    
                // Wait
                actionEvent.WaitOne();
            }
    
    
            private void Operate()
            {
                try
                {
                    // Begin
                    _threadEvent.Reset();
    
                    // Operate
                    while (true)
                    {
                        // Action
                        Action action = _actionQueue.Dequeue();
    
                        // Execute
                        if (action != null)
                        {
                            action();
                        }
                                            
                        // ThreadState
                        if (action == null)
                        {
                            lock (_syncRoot)
                            {
                                if (_threadState == ThreadState.Stopping)
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
                finally
                {
                    // End
                    lock (_syncRoot)
                    {
                        _threadState = ThreadState.Stopped;
                    }
                    _threadEvent.Set();
                }
            }
        }
    }
    
    namespace CLK.Threading
    {
        public class BlockingQueue<T>
        {
            // Fields        
            private readonly object _syncRoot = new object();
    
            private readonly WaitHandle[] _waitHandles = null;
    
            private readonly Queue<T> _itemQueue = null;
    
            private readonly Semaphore _itemQueueSemaphore = null;
    
            private readonly ManualResetEvent _itemQueueReleaseEvent = null;
    
    
            // Constructors
            public BlockingQueue()
            {
                // Default 
                _itemQueue = new Queue<T>();
                _itemQueueSemaphore = new Semaphore(0, int.MaxValue);
                _itemQueueReleaseEvent = new ManualResetEvent(false);
                _waitHandles = new WaitHandle[] { _itemQueueSemaphore, _itemQueueReleaseEvent };
            }
    
    
            // Methods
            public void Enqueue(T item)
            {
                lock (_syncRoot)
                {
                    _itemQueue.Enqueue(item);
                    _itemQueueSemaphore.Release();
                }
            }
    
            public T Dequeue()
            {
                WaitHandle.WaitAny(_waitHandles);
                lock (_syncRoot)
                {
                    if (_itemQueue.Count > 0)
                    {
                        return _itemQueue.Dequeue();
                    }
                }
                return default(T);
            }
    
            public void Release()
            {
                lock (_syncRoot)
                {
                    _itemQueueReleaseEvent.Set();
                }
            }
    
            public void Reset()
            {
                lock (_syncRoot)
                {
                    _itemQueue.Clear();
                    _itemQueueSemaphore.Close();
                    _itemQueueReleaseEvent.Reset();
                }
            }
        }
    }
    


  • 相关阅读:
    制作在线简历(一)——Loading与底部菜单
    然而这并没有什么卵用
    移动开发中Fiddler的那些事儿
    多种方法实现Loading(加载)动画效果
    总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解
    SQLServer和MySQL job和 event定时器的差别
    全局ID的重要性
    Windows操作系统上各种服务使用的端口号, 以及它们使用的协议的列表
    Linux发展历史图
    奇特的Local System权限(转载)
  • 原文地址:https://www.cnblogs.com/clark159/p/2658982.html
Copyright © 2020-2023  润新知