在WindowForm应用程序中主要的线程,是采用一种称为「Single-Threaded Apartment(STA)」的线程模型。这个STA线程模型,在线程内加入了讯息帮浦等等机制,减少开发人员撰写窗口程序的工作量。
而在开发类别库的时候,如果要使用类似的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(); } } } }
|