.NET中STAThread的使用详解

  在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();

  }

  }

  }

  }