C#多线程中等待线程池中的所有线程执行完毕后再执行下一个线程

摘要:
网上找的,做个笔记记录一下。有这么一个需求,就是巡检多台服务器是否都在线,点击巡检按钮后,按行读取DataGridView中的数据,并启行线程执行,这时会存在多个线程同时运行,但是什么时候给出用户提醒,说都巡检完成了呢,需要用到一个线程状态的检测。最后的效果是这样子的,多个线程对表格按行进行服务器的巡检,只有等所有的巡检线都结束后,等待线程才会弹出一个巡检完毕的提示框,在巡检的过程中,不会卡主界面。

网上找的,做个笔记记录一下。

有这么一个需求,就是巡检多台服务器是否都在线,点击巡检按钮后,按行读取DataGridView中的数据,并启行线程执行,这时会存在多个线程同时运行,但是什么时候给出用户提醒,说都巡检完成了呢,需要用到一个线程状态的检测。

最后的效果是这样子的,多个线程对表格按行进行服务器的巡检,只有等所有的巡检线都结束后,等待线程才会弹出一个巡检完毕的提示框,在巡检的过程中,不会卡主界面。

1、新建一个类,用于处理线程状态的计数,用于解决EventWaitHandle时线程不能超过64个的问题

 public classMutipleThreadResetEvent : IDisposable
    {
        private readonlyManualResetEvent done;
        private readonly inttotal;
        private longcurrent;
 
        /// <summary>
        ///构造函数
        /// </summary>
        /// <param name="total">需要等待执行的线程总数</param>
        public MutipleThreadResetEvent(inttotal)
        {
            this.total =total;
            current =total;
            done = new ManualResetEvent(false);
        }
 
        /// <summary>
        ///唤醒一个等待的线程
        /// </summary>
        public voidSetOne()
        {
            //Interlocked 原子操作类 ,此处将计数器减1
            if (Interlocked.Decrement(ref current) == 0)
            {
                //当所以等待线程执行完毕时,唤醒等待的线程
done.Set();
            }
        }
 
        /// <summary>
        ///等待所以线程执行完毕
        /// </summary>
        public voidWaitAll()
        {
            done.WaitOne();
        }
 
        /// <summary>
        ///释放对象占用的空间
        /// </summary>
        public voidDispose()
        {
            ((IDisposable)done).Dispose();
        }
    } 

2、定义一个结构体,用于存放线程需要的参数和MutipleThreadResetEvent

       structwebInfo
        {
            public intxh;
            public stringlx;
            public stringpath;
            public objectmre;
            //public ManualResetEvent mre;
        }

3、在DataGridView中使用

int num = DG_show.RowCount - 1;
            for (int i = 0; i < DG_show.RowCount - 1; i++)
            {
                DG_show.Rows[i].Cells["验证结果"].Value = "";
                DG_show.Rows[i].DefaultCellStyle.BackColor =Color.White;
            }

            //开始进行验证
            //manualEvents.Clear();  //以前的代码,可以删除
            PR1.Maximum =num;
            PR1.Minimum = 0;
            var countdown = newMutipleThreadResetEvent(num);
            webInfo info1;
            ThreadPool.SetMaxThreads(5,5);  //设置最大的线程数量
            for (int i = 0; i < DG_show.RowCount - 1; i++)
            {
                //ManualResetEvent mre = new ManualResetEvent(false);
                //manualEvents.Add(mre);
                info1.xh =i;
                //info1.mre = mre;
                info1.mre =countdown;
                info1.lx = DG_show.Rows[i].Cells["方式"].Value.ToString().Trim();
                info1.path = DG_show.Rows[i].Cells["地址"].Value.ToString().Trim();

                //Thread thread1 = new Thread(new ParameterizedThreadStart(CheckResult));
                //thread1.Start(info1);
          //进行巡检的线程 ThreadPool.QueueUserWorkItem(CheckResult, info1); } //等待所有巡检线程执行完毕的线程 Thread th1 = new Thread(newParameterizedThreadStart(WaitThreadEnd)); th1.Start(countdown);
CheckResult和WaitThreadEnd就是具体的业务处理

4、巡检线程和等待线程中的写法

巡检线程

private void CheckResult(objectinfo)
        {

            webInfo web =(webInfo)info;
            //... ...省略掉具体的业务过程
MutipleThreadResetEvent countdown = web.mre asMutipleThreadResetEvent;
            countdown.SetOne();
        }

等待巡检线程执行完毕的等待线程,其中执行一些启用主ui界面控件显示,进度条控件,按钮控件等操作,但是弹出的对话框有点问题,是在线程中弹出的,用户可能关注不到它。

public void WaitThreadEnd(objectobj)
        {
            MutipleThreadResetEvent countdown = obj asMutipleThreadResetEvent;
            countdown.WaitAll();
MessageBox.Show("服务器可访问性验证已经完成,验证通过" + js1.ToString() + "个,验证失败" + js2.ToString() + "个!", "验证提示", MessageBoxButtons.OK, MessageBoxIcon.Information); if(btn_start.InvokeRequired) { this.BeginInvoke(new Action<bool>((x) => { btn_start.Enabled = x; PR1.Visible = false; }), true); } }

运行起来后效果还不错,对于我们这种小白用户可以解决大部分的问题了。

免责声明:文章转载自《C#多线程中等待线程池中的所有线程执行完毕后再执行下一个线程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇java http返回值Result 工具类PHP中文乱码解决方案下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

WPF系列学习

1:WPF最小化到系统托盘 2:WPF程序单例运行 3:WPF中三种异常捕获:UI线程异常、非UI线程异常、Task线程异常 在窗体放一个按钮在单击事件执行如下代码来模拟。 private void Button_Click(objectsender, RoutedEventArgs e) { //t...

JVM 详解

1 jdk  和jre 的区别     jre 石 Java 运行环境,只能运行 class 不能编辑 Java文件,不能dubug。  2  jdk下面的  bin/jconsole.exe 监控 一些内存,线程,jvm 。 3 Java 的 层级 ,以前我们关注的是三面 三次。jvm 是最下面一层    4 Java的  作者是  詹姆斯·高斯林   ...

C# 当前程序所有线程

using System.Linq; var threads = System.Diagnostics.Process.GetCurrentProcess().Threads;var count = threads.Count;var actived = threads.Cast<ProcessThread>().Where(t => t...

JAVA协程 纤程 与Quasar 框架

ava使用的是系统级线程,也就是说,每次调用new Thread(....).run(),都会在系统层面建立一个新的线程,然鹅新建线程的开销是很大的(每个线程默认情况下会占用1MB的内存空间,当然你愿意的话可以用-Xss来调小点),更不要说线程切换带来的开销了 为了节省开销,程序员玩出了很多花样。 最常用的是线程池(线程复用,但是完全无法处理阻塞调用的问题...

QT之深入理解QThread

QT之深入理解QThread       理解QThread之前需要了解下QThread类,QThread拥有的资源如下(摘录于QT 5.1 帮助文档):       在以上资源中,本文重点关注槽:start();信号:started()、finished();受保护的方法:run()、exec();   理解QThread     QThread与通常所...

正确使用Android性能分析工具——TraceView

TraceView界面 现来看一下整个界面的图,整个界面包括上下两部分,上面是你测试的进程中每个线程的执行情况,每个线程占一行;下面是每个方法执行的各个指标的值 上面一部分是你测试进程的中每个线程运行的时间线,下图中可以可以看到,主要只有一个main线程在执行,因为我滑动了一下列表,main线程(UI线程)正在进行绘制View呢~~ 然后我点击了序号为13...