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


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

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

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

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

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

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

           struct webInfo
            {
                public int xh;
                public string lx;
                public string path;
                public object mre;
                //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 = new MutipleThreadResetEvent(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(new ParameterizedThreadStart(WaitThreadEnd)); th1.Start(countdown);
    CheckResult和WaitThreadEnd就是具体的业务处理

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

    巡检线程

            private void CheckResult(object info)
            {
    
                webInfo web = (webInfo)info;
                //... ...省略掉具体的业务过程
    
                MutipleThreadResetEvent countdown = web.mre as MutipleThreadResetEvent;
                countdown.SetOne();
            }

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

    public void WaitThreadEnd(object obj)
            {
                MutipleThreadResetEvent countdown = obj as MutipleThreadResetEvent;
                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); } }

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

  • 相关阅读:
    快的打车 技术部 在 杭州 招聘 #年前面试 年后入职#架构师
    王大锤_百度百科
    2013年总结
    泥沙俱下_百度百科
    thank you letter
    上海投行需要一大群JAVA,C++,C#,UNIX.走过路过不要错过!过完年想换工作看过来初级资深都有
    外省人员-办理护照_百度经验
    敬请贤者:WEB、IOS开发(2年以上经验,大专);CTO、产品经理,运营专员 电商服装鞋饰买手(2年以上经验,服装或鞋类);体验店店长 (2年以上经验,服装或鞋类) 工作地点:丰台南苑路;有意者小窗QQ2211788980
    “快的打车”创始人陈伟星的新项目招人啦,高薪急招Java服务端/Android/Ios 客户端研发工程师/ mysql DBA/ app市场推广专家,欢迎大家加入我们的团队!
    【深圳,武汉】一加科技(One Plus)招聘,寻找不...
  • 原文地址:https://www.cnblogs.com/wjbych/p/14092000.html
Copyright © 2020-2023  润新知