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. sublime text3插件的安装

    1.安装Package Control提示Package Control:There are no packages available for installation, 解决方案:删除Packag ...

  2. jenkins持续集成工作原理

    转载https://www.cnblogs.com/liyuanhong/p/6548925.html 片段 这里是选择Gitlab作为git server.Gitlab的功能和Github差不多,但 ...

  3. python -- 将string转换成dict的方法

    装载自:http://smilejay.com/2014/10/convert_string_to_dict_python/ 我将数据库连接相关的一些用户名/密码/host/port等各种东西作为一个 ...

  4. UVALive - 6837 Kruskal+一点性质(暴力枚举)

    ICPC (Isles of Coral Park City) consist of several beautiful islands. The citizens requested constru ...

  5. 循环获取某个class下的多个select的选中值

    //循环获取某个class下的多个select的选中值 function eachSelect(cla){ var val = ""; $("."+cla).e ...

  6. mysql修改数据表自增步长

    可以修改系统变量 auto_increment_increment mysql> SHOW VARIABLES LIKE 'auto_inc%'; +---------------------- ...

  7. RunLoop 之初探

    你好2019!一起努力呀! 1.什么是runloop runloop是通过内部维护的事件循环对事件/消息进行管理的一个对象. 事件循环(Event loop):通俗的解释:没有消息处理的时候,休眠以避 ...

  8. java获取服务器基本信息

    实现步骤: (1)创建servlet BrowserServer (2)调用HttpServletRequest对象的getServerName()方法获取服务器名称 (3)调用HttpServlet ...

  9. php 获取当前完整url地址

    echo $url = $_SERVER["REQUEST_SCHEME"].'://'.$_SERVER["SERVER_NAME"].$_SERVER[&q ...

  10. linux 相关命令记录

    NetworkManager关闭及禁用 关闭:systemctl stop NetworkManager 禁用:systemctl disable NetworkManager 查看日志:journa ...