- System.Threading.Thread类主要使用Thread构造函数、Priority属性、void Start、void Sleep(int sleepTime)、static Thread CurrentThread(返回当前运行的Thread对象);在.NET Compact Framework中创建并启动Thread的步骤:
创建一个System.Threading.ThreadStart的实例,向其传递一个void func()类型的方法作为参数;
创建一个System.Threading.Thread的实例,将ThreadStart传递给Thread的构造函数;
调用Thread.Start()启动Thread;
System.Threading.Thread m_singlesThread;
System.Threading.ThreadStart m_singlesThreadStart;
m_singlesThreadStart = new
System.Threading.ThreadStart(SinglesCounter);
m_singlesThread = new System.Threading.Thread(m_singlesThreadStart);
m_singlesThread.Start();
- 通过调用static Thread.Sleep(ms)能够令调用本方法的线程休眠特定的时间,这种方法指定的时间是休眠的最小时间,并不保证到达时间后线程一定恢复运行;
- .NET Compact Framework中,控件不能被不具有所有权的Thread更新,另外desktop版本中支持的Form.BeginInvoke和 Form.EndInvoke在Compact中不支持;为了克服这个问题,先创建一个更新UI method的delegate,然后再Thread中通过Form.Invoke调用这个delegate,这种method必须是 EventHandler类型;
class MyForm : Form{
ListBox lbData ;
MyForm() {
InitializeComponent(); // Create form controls
Thread t = new Thread(new ThreadStart(Work1_));
t.Start() ; // Runs Work1_ on a background thread
}
private Queue qData = new Queue(); // Visible to all member functions on all threads
void Work1_(){
// Wrap AddItem in delegate
EventHandler eh = new EventHandler(AddItem);
StreamReader rdr1 = new StreamReader(@"/My Documents/DataFile.dat");
string line = rdr1.ReadLine();
while(line != null) {
lock(qData){ // Synchronize queue acess
qData.Enqueue(line); // Store line value in queue
}
lbData.Invoke(eh); // Transfer control to thread that created lbData
line = rdr1.ReadLine();
}
}
void AddItem(object o, EventArgs e)
{
string line = null;
lock(qData){ // Synchronize queue acess
line = (string)qData(); // Get data from queue
}
lbData.Items.Add(line); // Update list box
}
}
- .NET Compact Framework中,一个Process无法在还有Thread运行的时候关闭;可以通过重载Form.OnClosing()来检查是否还有Thread在运行
//warps the Form.Close in order to be invked in thread
private void ShutDown(object o, EventArgs e)
{
mainForm.Close();
}
protected override void OnClosing(CancelEventArgs e)
{
if (m_SinglesThreadRunning)
{
e.Cancel = true;
MessageBox.Show("Will wait for threads to stop, then quit");
m_QuitRequested = true;
}
else
{
Close();
}
}
// Runs on separate thread
private void SinglesCounter()
{
int l_currentSinglesCount = 0;
while (!m_QuitRequested)
{
...
}
m_SinglesThreadRunning = false;
mainForm.Invoke(new EventHandler(ShutDown));
}
- Mutex Class用于协调Thread,确保一段代码在某个时刻只会被一个Thread执行;同一时刻只有一个Thread能获取Mutex,其他请求Mutex的Thread都会阻塞直到所有者释放Mutex;使用Mutex的步骤为:
创建一个Mutex实例,传递false参数使得创建线程不获取这个Mutex;
在进入关键代码前调用Mutex.WaitOne()获取Mutex;
在完成关键代码后调用Mutex.ReleaseMutex()来释放Mutex;
// Create instance of Mutex class. The variable holding the
// reference to this Mutex must be visible to the block of code
// that will be protected.
m_Mutex = new System.Threading.Mutex(false);
// This is the code which we only want one thread at a time to execute
// This call blocks until we acquire the Mutex
m_Mutex.WaitOne();
// Put code here that only is executed by one thread at a time
// Done, let others enter this code block now
m_Mutex.ReleaseMutex();
- .NET Compact Framework不支持Thread.Suspend和Thread.Resume,如果Thread中一直在循环执行代码,可以通过Mutex模拟Suspend和Resume:
使用false参数创建一个Mutex对象;
在循环的开始调用Mutex.WaitOne();
在循环的结束处调用Mutex.ReleaseMutex();
要想Suspend,则在Thread外部调用Mutex.WaitOne(),在当前循环结束后Thread进入阻塞;
要想Resume,则在Thread外部调用Mutex.ReleaseMutex();
- .NET Compact Framework也不支持Thread.Join()来等待线程结束,可以使用Mutex来模拟这个行为:
// This is the code that runs in the child thread
private void DoSomeWork()
{
m_ThreadAliveMutex.WaitOne();
m_isThreadRunning = true;
// Do some work here. We'll just sleep to simulate work that
// took a while
System.Threading.Thread.Sleep(10000);
// Release the "alive" mutex on thread exit, indicating that
// this thread is dying.
m_ThreadAliveMutex.ReleaseMutex();
}
// This is the code that runs in the parent thread
// m_isThreadRunning is a bool class member
// m_ThreadAliveMutex is a Mutex class member
m_isThreadRunning = false;
m_ThreadAliveMutex = new System.Threading.Mutex(false);
m_threadStart = new System.Threading.ThreadStart(DoSomeWork);
m_workerThread = new System.Threading.Thread(m_threadStart);
m_workerThread.Start();
// We actually need to know that the thread has started before
// we wait for it.
while (m_isThreadRunning == false)
{
System.Threading.Thread.Sleep(100);
}
m_ThreadAliveMutex.WaitOne();
m_ThreadAliveMutex.ReleaseMutex();
MessageBox.Show("Worker thread has stopped");
- Monitor Class用于防止对某个数据对象的并发访问,确保某个时刻只有一个Thread在访问这个数据;在要独占访问数据对象的时候,调用 System.Threading.Monitor.Enter(object),在完成对数据的独占访问后,调用 System.Threading.Monitor.Exit(object);
System.Threading.Monitor.Enter(m_CustomerBankInfo);
// Access m_CustomerBankInfo
// Now done with m_CustomerBankInfo
System.Threading.Monitor.Exit(m_CustomerBankInfo);
- ThreadPool Class在内部维护了一个小数量的Thread,用于执行传递进来的特定method;当method返回后,执行这个method的thread被归 还给pool;这对于要大量执行、但是每次执行时间都很短的Thread很有好处;使用ThreadPool的步骤是:
创建一个无参数返回值为void的method;
创建一个WaitCallback的实例,将method的名字作为参数传递;
调用static ThreadPool.QueueUserWorkItem方法,将WaitCallback实例作为参数传递;
m_singlesWaitCallBack = new WaitCallback(SinglesCounter);
ThreadPool.QueueUserWorkItem(m_singlesWaitCallBack);
- Timer类非常时候周期性执行的代码,可以讲这些代码放在Tick方法中,但是这些代码的执行时间应该很短,否则使用Thread更加适合;Timer可以更新那些创建Timer的Thread所拥有的控件;
// Code in the Tick method is executed every 1000 milliseconds
singlesTimer.Interval = 1000;
// suspend the timer
myTimer.Enabled = false;
// Do some work with the timer suspended
// enable the timer again
myTimer.Enabled = true;
private void singlesTimer_Tick(object sender, System.EventArgs e)
{
this.txtSingles.Text = Convert.ToString(m_SinglesCount);
m_SinglesCount = m_SinglesCount + 1;
}
System.Threading.Interlocked Class提供了原子化的变量增减和更新操作;
System.Threading.Interlocked.Increment(ref my_integer);
System.Threading.Interlocked.Decrement(ref my_integer);
System.Threading.Interlocked.Exchange(ref my_integer, new_value);