[.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(); } } } }
期許自己~
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。