zoukankan      html  css  js  c++  java
  • 线程间通讯:WaitHandler使用实例及分析

    实例效果:

    1.点击“启动线程”会启动一个线程t每隔2秒在listbox上插入一条新记录。

    2.点击“关闭线程”会停止线程t,但不是马上停止而是等待线程t当次循环的工作后再结束。

    Form1.cs

     1 using System;
    2 using System.Collections.Generic;
    3 using System.ComponentModel;
    4 using System.Data;
    5 using System.Drawing;
    6 using System.Linq;
    7 using System.Text;
    8 using System.Windows.Forms;
    9 using System.Threading;
    10
    11 namespace TestThread
    12 {
    13 public partial class Form1 : Form
    14 {
    15 private ManualResetEvent Stop = new ManualResetEvent(false);//用于告诉线程t要关闭t线程
    16 private ManualResetEvent Stoped = new ManualResetEvent(false);//用于告诉主线程t线程已关闭
    17 Thread t = null;
    18 private delegate void SetUIDelegate(string val);//用于线程t操作ui控件
    19
    20 public Form1()
    21 {
    22 InitializeComponent();
    23 }
    24
    25 private void button1_Click(object sender, EventArgs e)//“启动线程”
    26 {
    27 MyThread mt = new MyThread(Stop, Stoped);
    28 mt.UIEvent += (val) =>
    29 {
    30 if (lbx.InvokeRequired)
    31 lbx.Invoke(new SetUIDelegate(SetUI), val);
    32 else
    33 lbx.Items.Add(val);
    34 };
    35 t = new Thread(() =>
    36 {
    37 mt.Run();
    38 });
    39 t.Start();
    40 }
    41
    42 private void button2_Click(object sender, EventArgs e)//“关闭线程”
    43 {
    44 if (null!=t&&t.IsAlive)//若线程t存在并存活才需关闭
    45 {
    46 Stop.Set();//发出指令告诉线程t:你是时候死了!
    47
    48 while (t.IsAlive)//因线程t不是马上自尽(也许还要吃个包、喝口茶在上吊哦!),所以要继续检查它是否存活
    49 {
    50 if (Stoped.WaitOne(0, false))//阻塞当前线程(这里设置阻塞0秒),就是看看线程t死了没
    51 {
    52 button1.Enabled = false;
    53 }
    54 Application.DoEvents();//因ui线程一直在检查线程t的死活,弄得其他需要ui线程的处理都无法进行,加上这句ui线程就有时间理睬一下其他处理了,以免画面假死!
    55 }
    56 }
    57 }
    58
    59 private void SetUI(string val)
    60 {
    61 lbx.Items.Add(val);
    62 }
    63 }
    64 }

    MyThread.cs

     1 using System;
    2 using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5 using System.Threading;
    6
    7 namespace TestThread
    8 {
    9 public delegate void SetUI(string val);
    10
    11 class MyThread
    12 {
    13 private ManualResetEvent Stop = null;
    14 private ManualResetEvent Stoped = null;
    15 public event SetUI UIEvent;
    16
    17 public MyThread(ManualResetEvent stop,ManualResetEvent stoped)
    18 {
    19 Stop = stop;
    20 Stoped = stoped;
    21 }
    22
    23 public void Run()
    24 {
    25 int i = 0;
    26 while (true)
    27 {
    28 Thread.Sleep(2000);//睡2秒再工作吧!
    29 UIEvent(i.ToString());//操作ui控件
    30 i++;
    31 if (Stop.WaitOne(0, false))//阻塞当前线程(这里又只阻塞0秒),直到ui线程赐死线程t
    32 {
    33 Stoped.Set();//告诉ui线程它要自杀了
    34 break;//自杀去了
    35 }
    36 }
    37 }
    38 }
    39 }

    子线程之死可以有两种方式:1、ui线程中调用t.Abort(),为它杀,也许线程t还有些事没做但已经没有机会了;2、让线程t退出或调用Thread.CurrentThread.Abort(),为自杀,这样线程t就可以在临死前了结心愿了。而上述功能就属于让线程t自杀,下面进一步分析。

    线程t无缘无故是不会自杀的,而ui线程要它自刎就必须发出一条命令,而这条命令就是ManualResetEvent对象。先看一看类结构

    可以看到ManualResetEvent类有一个孪生兄弟AutoResetEvent类,它们的祖父是WaitHandle类。

    ManualResetEvent实例有终止和非终止两个状态,在初始化时可以设定。它的Set()方法会将实例设为终止状态,Reset()方法会将实例设为非终止状态。而WaitOne()就是阻塞当前线程直到实例被设为终止状态,而WaitOne()方法有多个重载方法,可以设定阻塞时间,超过了阻塞时间实例状态依然为非终止的话就放弃阻塞,让线程继续执行WaitOne语句以下的内容。WaitOne返回值为Boolean值,表示实例状态是否为终止状态。

    AutoResetEvent类跟ManualResetEvent类只有一点区别就是它会自动把实例设为非终止状态。

    而使用WaitHandle的静态方法WaitAll或WaitAny可以检查多个ManualResetEvent实例和AutoResetEvent实例的状态。

    上述代码中线程t自杀时通过另一个ManualResetEvent实例告诉ui线程“我挂了!”,好让ui线程做善后工作。

    检查线程t是否已死的过程是一直占用ui线程的,而窗口上控件的交互也是由ui线程来处理,这时会出现画面假死的状态,如果发出了调用ui线程处理其他事件的话就会有异常。这时加上一句Application.DoEvents()表示让处理当前消息队列中的所有window消息,就是说ui线程抽出一部分时间来处理消息队列中的其他消息(如界面的交互),而不是完成了第一个消息再着手后面的消息。注意:这时ui线程是可用的,只是正忙于处理第一个消息,如果ui线程挂起来了、阻塞了或死了Application.DoEvents()无法使让ui线程处理消息队列中的其他消息。


    要实现上述的子线程自杀方式也可以用两个静态变量来做控制,至于实现方法我这里就不写了。



    欢迎添加我的公众号一起深入探讨技术手艺人的那些事!

    如果您觉得本文的内容有趣就扫一下吧!捐赠互勉!
      

  • 相关阅读:
    网络编程
    正则表达式
    对空气质量历史数据的爬取
    通过移动设备行为数据预测性别年龄
    电影口碑与海报图像的相关性分析
    微博情感分析
    《python3网络爬虫开发实战》--验证码的识别
    python编程快速上手
    Echarts树图定制详解
    Servlet学习笔记【2】---Http数据包
  • 原文地址:https://www.cnblogs.com/fsjohnhuang/p/2319253.html
Copyright © 2011-2022 走看看