[.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();

            }

        }

    }

}


你可能感兴趣的:(thread)