• 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 
  • 相关阅读:
    【Spring-MVC】
    【多线程】线程池关闭
    【DDD】基于事件驱动EDA -- 待完成
    【DDD】编码实战
    【Elastic Search】01- 原理
    【DDD】基于DDD的分层设计
    【DDD】Thoughtworks笔记(编码样例) -- 未完成
    【DDD】Thoughtworks笔记(目录划分、异常设计)
    平方和求余
    Factoring a Polynomial
  • 原文地址:https://www.cnblogs.com/adaiye/p/913214.html
Copyright © 2020-2023  润新知