The main thread in the windowform application is a thread model called "Single-threaded apartment (STA. This stathread model is added to the thread with a messaging engine and other mechanisms to reduce the workload for developers to write window programs. For more information, see [object-oriented.
When developing the category library, if you want to use a similar stathread model, you can use the categories provided by the following program code.
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(); } } }}