.Net Compact Framework开发(2)——Thread和Timer

来源:互联网 发布:中国石油网络教育 编辑:程序博客网 时间:2024/04/24 05:13
  • System.Threading.Thread类主要使用Thread构造函数、Priority属性、void Startvoid 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.EndInvokeCompact中不支持;为了克服这个问题,先创建一个更新UI methoddelegate,然后再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,其他请求MutexThread都会阻塞直到所有者释放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.SuspendThread.Resume,如果Thread中一直在循环执行代码,可以通过Mutex模拟SuspendResume

    使用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返回后,执行这个methodthread被归 还给pool;这对于要大量执行、但是每次执行时间都很短的Thread很有好处;使用ThreadPool的步骤是:

    创建一个无参数返回值为voidmethod
   
创建一个WaitCallback的实例,将method的名字作为参数传递;
   
调用static ThreadPool.QueueUserWorkItem方法,将WaitCallback实例作为参数传递;

m_singlesWaitCallBack = new WaitCallback(SinglesCounter);
ThreadPool.QueueUserWorkItem(m_singlesWaitCallBack);

  • Timer类非常时候周期性执行的代码,可以讲这些代码放在Tick方法中,但是这些代码的执行时间应该很短,否则使用Thread更加适合;Timer可以更新那些创建TimerThread所拥有的控件;

// 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);