1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System;
using System.Threading;
 
namespace ConsoleApplication1
{
    class Program
    {
        private static AutoResetEvent[] events;
 
        static void Main(string[] args)
        {
            int threadNum = 10;
            Thread[] thread = new Thread[threadNum];
 
            events = new AutoResetEvent[threadNum];
 
            for (int i = 0; i < threadNum; i++)
            {
                var waithandler = new AutoResetEvent(false);
                events[i] = waithandler;
                ThreadStart starter = delegate
                {
                    var param = new Tuple<string, AutoResetEvent>("test print:" + i, waithandler);
                    Print(param);
                };
                thread[i] = new Thread(starter)
                {
                    Name = "thread" + i.ToString()
                };
            }
 
            for (int i = 0; i < threadNum; i++)
            {
                thread[i].Start();
            }
 
            WaitHandle.WaitAll(events);
            Console.WriteLine("Completed!");
            Console.Read();
 
        }
 
        private static void Print(object param)
        {
            var p = (Tuple<string, AutoResetEvent>)param;
            Console.WriteLine(Thread.CurrentThread.Name + ": Begin!");
            Console.WriteLine(Thread.CurrentThread.Name + ": Print" + p.Item1);
            Thread.Sleep(300);
            Console.WriteLine(Thread.CurrentThread.Name + ": End!");
            p.Item2.Set();
        }
    }
}

一次性地Set,其实使用ManualResetEvent就足够了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;
using System.Collections.Generic;
using System.Threading;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var waits = new List<EventWaitHandle>();
            for (int i = 0; i < 10; i++)
            {
                var handler = new ManualResetEvent(false);
                waits.Add(handler);
                new Thread(new ParameterizedThreadStart(Print))
                {
                    Name = "thread" + i.ToString()
                }.Start(new Tuple<string, EventWaitHandle>("test print:" + i, handler));
            }
            WaitHandle.WaitAll(waits.ToArray());
            Console.WriteLine("Completed!");
            Console.Read();
 
        }
 
        private static void Print(object param)
        {
            var p = (Tuple<string, EventWaitHandle>)param;
            Console.WriteLine(Thread.CurrentThread.Name + ": Begin!");
            Console.WriteLine(Thread.CurrentThread.Name + ": Print" + p.Item1);
            Thread.Sleep(300);
            Console.WriteLine(Thread.CurrentThread.Name + ": End!");
            p.Item2.Set();
        }
 
    }
}

C# 多线程的等待所有线程结束的一个问题的更多相关文章

  1. C# 多线程的等待所有线程结束

      //前台线程和后台线程唯一区别就是:应用程序必须运行完所有的前台线程才可以退出://而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,//所有的后台线程在应用程序退出时都会自动结束 ...

  2. CountDownLatch 多线程,等待所有线程结束

    CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 主要方法 public CountDownLatch(int count); 构造 ...

  3. C# 多线程的等待所有线程结束 用 ManualResetEvent 控制

    using System; using System.Collections.Generic; using System.Threading; namespace ConsoleApplication ...

  4. Java多线程之以7种方式让主线程等待子线程结束

    记一次主线程等待子线程结束的多种方法的学习 在学习多线程时,最开始遇到的问题其实是"计算子线程运行时间",写到最后发现本文和标题更为符合,但是仍然基于问题:"在主线程中获 ...

  5. java 多线程 Thread.join子线程结束父线程再运行;join(long):等待超时毫秒数

    Join的使用 目的:当子线程运行结束后,父线程才能再继续运行 /** * @ClassName ThreadJoinExample * @projectName: object1 * @author ...

  6. Java Thread.join()详解--父线程等待子线程结束后再结束

    目录(?)[+] 阅读目录 一.使用方式. 二.为什么要用join()方法 三.join方法的作用 join 四.用实例来理解 打印结果: 打印结果: 五.从源码看join()方法   join是Th ...

  7. Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束

    Java 5 开始引入的 Concurrent 并发软件包里面的 CountDownLatch 其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是 ...

  8. 线程:Java主线程等待子线程结束

    使用Thread.join()方法: public class App { public static void main(String[] args) { testMain(); } public ...

  9. Java如何等待子线程执行结束

    工作中往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线 ...

随机推荐

  1. StackExchange.Redis学习笔记(一) Redis的使用初探

    Redis Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化. 与其它键值数据存储相比,Redis有一组相对丰富的数据类型. Redis可以将数据复制到任意数量的从机中 Redis的安装 官 ...

  2. Struts2通配符

    action: struts: or: 请求路径:

  3. iOS 封装一个带复制功能的UILabel

    我们发现UILabel不在为我们提供长按弹出复制等操作了, 我们来继承UILabel自己写一个带复制功能的UILabel. 代码: #import "CopyLabel.h" @i ...

  4. Qt串口接收使用多个LCD控件显示不同的数据

    https://blog.csdn.net/qq_30976353/article/details/84836124 参考链接

  5. CentOS 7紧急救援模式修改root用户密码的方法

    最近无聊在网上搜索linux系统root用户密码破解方法,看来很多朋友的博文,同时也试了一下,但是感觉他们写的还是不是很清晰.简洁,因此自己就心血来潮写了这篇博文,提供一个比较清晰的思路给新手,如果有 ...

  6. 【Linux】管理文件系统

    文件系统概念: 文件系统是指文件的组织与管理结构,是一个有关于磁盘中各种有用信息的记录——即是保存以下信息的结构记录表 当前所使用磁盘的容量信息 磁盘的可用信息,包括已占用和剩余的空间: 文件与目录的 ...

  7. html-表单标签

    表单标签 * 可以提交数据到**网站上的服务器,这个过程可以使用表单标签实现 * <form></form>:定义一个表单的范围 - 属性 ** action:提交到地址,默认 ...

  8. PhpStorm 克隆下来的项目改动,版本控制不起效果

    打开的目录 —>多个 git项目—>版本控制无法监控. 打开的目录 —>一个 git项目—>版本控制可以监控.

  9. 在AI人工智能中如何巧妙学习大数据编程,成为五十万年薪的佼佼者

    编辑 ai狗年 大数据和人工智能的关系,首先要说什么是大数据.这些年来,大数据先是被神化,继而又被妖魔化,到了今天,其实谁也不知道别人所谓的大数据指的是什么.我大数据从业者,建了一个大数据资源共享群1 ...

  10. Hadoop(二)CentOS7.5搭建Hadoop2.7.6完全分布式集群

    一 完全分布式集群(单点) Hadoop官方地址:http://hadoop.apache.org/ 1  准备3台客户机 1.1防火墙,静态IP,主机名 关闭防火墙,设置静态IP,主机名此处略,参考 ...