C#中的线程

by:Alex Fr  译:adaiye


简介

.NET框架提供很多方法来实现多线程编程。我想展示如何通过同步访问用户接口去运行一个工作线程(例如,一个读取记录集并要在一个窗体中填充控件的线程)。
运行线程,我用:
  • 线程实例和主线程函数
  • 两个使线程停止的事件。第一个事件是设置何时主线程想停止工作线程,第二个事件是工作线程设置何时想真正停止。
.NET只允许Control中创建的线程去调用System.Windows.Forms.Control的函数。要想从另一个线程中访问System.Windows.Forms.Control中的函数,你需要使用Control.Invoke(同步调用)或Control.BeginInvoke(异步调用)函数。比如说显示数据库的记录,我们就需要Invoke
要想实现这个,我们要用:
  • 一个为了访问窗体的委托类型。委托实例和函数调用使用这个委托。
  • 从工作线程来的函数调用。
下一个问题是准确的停止工作线程。做这些的步骤是:
  • 启动“停止线程”事件;
  • 等待“线程已经停止”事件;
  • Application.DoEvents函数等待事件处理消息。这是为了防止死锁的,因为工作线程的Invoke调用是被主线程所处理的。
线程函数检查每个迭代,看“停止线程”事件是否发生了。如果这个事件发生了,函数调用清理操作,触发“线程已经停止”事件,并返回。
Demo有两个类:MainForm和LongProcessLongProcess.Run函数在线程中被执行,它会用几行数据来填充列表。工作线程可能会自然停止,或者当用户按下"Stop Thread"按钮或关闭窗体时停止。

源代码


  1 // MainForm.cs
  2 
  3 namespace WorkerThread
  4 {
  5     // delegates used to call MainForm functions from worker thread
  6     public delegate void DelegateAddString(String s);
  7     public delegate void DelegateThreadFinished();
  8 
  9     public class MainForm : System.Windows.Forms.Form
 10     {
 11         // 
 12 
 13         // worker thread
 14         Thread m_WorkerThread;
 15 
 16         // events used to stop worker thread
 17         ManualResetEvent m_EventStopThread;
 18         ManualResetEvent m_EventThreadStopped;
 19 
 20         // Delegate instances used to call user interface functions 
 21         // from worker thread:
 22         public DelegateAddString m_DelegateAddString;
 23         public DelegateThreadFinished m_DelegateThreadFinished;
 24 
 25         // 
 26 
 27         public MainForm()
 28         {
 29             InitializeComponent();
 30 
 31             // initialize delegates
 32             m_DelegateAddString = new DelegateAddString(this.AddString);
 33             m_DelegateThreadFinished = new DelegateThreadFinished(this.ThreadFinished);
 34 
 35             // initialize events
 36             m_EventStopThread = new ManualResetEvent(false);
 37             m_EventThreadStopped = new ManualResetEvent(false);
 38 
 39         }
 40 
 41         // 
 42 
 43         // Start thread button is pressed
 44         private void btnStartThread_Click(object sender, System.EventArgs e)
 45         {
 46             // 
 47             
 48             // reset events
 49             m_EventStopThread.Reset();
 50             m_EventThreadStopped.Reset();
 51 
 52             // create worker thread instance
 53             m_WorkerThread = new Thread(new ThreadStart(this.WorkerThreadFunction));
 54 
 55             m_WorkerThread.Name = "Worker Thread Sample";   // looks nice in Output window
 56 
 57             m_WorkerThread.Start();
 58 
 59         }
 60 
 61 
 62         // Worker thread function.
 63         // Called indirectly from btnStartThread_Click
 64         private void WorkerThreadFunction()
 65         {
 66             LongProcess longProcess;
 67 
 68             longProcess = new LongProcess(m_EventStopThread, m_EventThreadStopped, this);
 69 
 70             longProcess.Run();
 71         }
 72 
 73         // Stop worker thread if it is running.
 74         // Called when user presses Stop button or form is closed.
 75         private void StopThread()
 76         {
 77             if ( m_WorkerThread != null  &&  m_WorkerThread.IsAlive )  // thread is active
 78             {
 79                 // set event "Stop"
 80                 m_EventStopThread.Set();
 81 
 82                 // wait when thread  will stop or finish
 83                 while (m_WorkerThread.IsAlive)
 84                 {
 85                     // We cannot use here infinite wait because our thread
 86                     // makes syncronous calls to main form, this will cause deadlock.
 87                     // Instead of this we wait for event some appropriate time
 88                     // (and by the way give time to worker thread) and
 89                     // process events. These events may contain Invoke calls.
 90                     if ( WaitHandle.WaitAll(
 91                         (new ManualResetEvent[] {m_EventThreadStopped}), 
 92                         100,
 93                         true) )
 94                     {
 95                         break;
 96                     }
 97 
 98                     Application.DoEvents();
 99                 }
100             }
101         }
102 
103         // Add string to list box.
104         // Called from worker thread using delegate and Control.Invoke
105         private void AddString(String s)
106         {
107             listBox1.Items.Add(s);
108         }
109 
110         // Set initial state of controls.
111         // Called from worker thread using delegate and Control.Invoke
112         private void ThreadFinished()
113         {
114             btnStartThread.Enabled = true;
115             btnStopThread.Enabled = false;
116         }
117 
118     }
119 }
120 
121 // LongProcess.cs
122 
123 namespace WorkerThread
124 {
125     public class LongProcess
126     {
127         // 
128     
129         // Function runs in worker thread and emulates long process.
130         public void Run()
131         {
132             int i;
133             String s;
134 
135             for (i = 1; i <= 10; i++)
136             {
137                 // make step
138                 s = "Step number " + i.ToString() + " executed";
139 
140                 Thread.Sleep(400);
141 
142                 // Make synchronous call to main form.
143                 // MainForm.AddString function runs in main thread.
144                 // (To make asynchronous call use BeginInvoke)
145                 m_form.Invoke(m_form.m_DelegateAddString, new Object[] {s});
146 
147 
148                 // check if thread is cancelled
149                 if ( m_EventStop.WaitOne(0true) )
150                 {
151                     // clean-up operations may be placed here
152                     // 
153 
154                     // inform main thread that this thread stopped
155                     m_EventStopped.Set();
156 
157                     return;
158                 }
159             }
160 
161             // Make synchronous call to main form
162             // to inform it that thread finished
163             m_form.Invoke(m_form.m_DelegateThreadFinished, null);
164         }
165 
166     }
167 }
168 
169 
170 
171 
172 
posted @ 2007-10-03 00:22  随风逝去(叶进)  阅读(766)  评论(0编辑  收藏  举报
Free Web Counter
Free Web Counter