.NET中STAThread的使用详解
程序员文章站
2024-03-01 15:38:46
在windowform应用程序中主要的线程,是采用一种称为「single-threaded apartment(sta)」的线程模型。这个sta线程模型,在线程内加入了讯息...
在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();
}
}
}
}