C# 多线程的等待所有线程结束
//前台线程和后台线程唯一区别就是:应用程序必须运行完所有的前台线程才可以退出;
//而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,
//所有的后台线程在应用程序退出时都会自动结束。
通过匿名委托或Lambda表达式来为Thread的构造方法赋值
Thread thread3 = new Thread(delegate() { Console.WriteLine("匿名委托"); });
thread3.Start();
Thread thread4 = new Thread(( ) => { Console.WriteLine("Lambda表达式"); });
thread4.Start();
二、 定义一个线程类
我们可以将Thread类封装在一个MyThread类中,以使任何从MyThread继承的类都具有多线程能力。MyThread类的代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace MyThread
{
abstract class MyThread
{
Thread thread = null; abstract public void run(); public void start()
{
if (thread == null)
thread = new Thread(run);
thread.Start();
}
}
}
可以用下面的代码来使用MyThread类。
class NewThread : MyThread
{
override public void run()
{
Console.WriteLine("使用MyThread建立并运行线程");
}
} static void Main(string[] args)
{ NewThread nt = new NewThread();
nt.start();
}
如果使用在第二节定义的MyThread类,传递参数会显示更简单,代码如下:
class NewThread : MyThread
{
private String p1;
private int p2;
public NewThread(String p1, int p2)
{
this.p1 = p1;
this.p2 = p2;
} override public void run()
{
Console.WriteLine(p1);
Console.WriteLine(p2);
}
} NewThread newThread = new NewThread("hello world", );
newThread.start();
EventWaitHandle(等待事件句柄)
EventWaitHandle是一个在线程处理上的类,它可以和WaitHandle配合使用完成多线程任务等待调度,并且在主线程中统一处理想要的结果。
private List<string> test()
{
List<string> list = new List<string>();
//创建等待事件句柄集合
var watis = new List<EventWaitHandle>();
for (int i = ; i < ; i++)
{
//创建句柄 true终止状态
var handler = new ManualResetEvent(false);
watis.Add(handler);
//将要执行的方法参数化
ParameterizedThreadStart start = new ParameterizedThreadStart(selectData);
//创建线程,传入线程参数
Thread t = new Thread(start);
//启动线程
t.Start(new Tuple<int, EventWaitHandle, List<string>>(i, handler,list));
}
//等待句柄
WaitHandle.WaitAll(watis.ToArray());
return list;
}
首先创建了一个EventWaitHandle的list,这个list将用于来添加所有的需要执行的等待事件句柄
然后将需要参与等待的任务(一个方法)参数化传入线程初始化的构造
在线程启动时,将与之对应的EventWaitHandle子类ManualResetEvent的对象传入需要调用的任务(方法)中
最后使用WaitHandle.WaitAll执行所有的等待事件句柄
private static void selectData(object param)
{
Tuple<int, EventWaitHandle,List<string>> t = (Tuple<int, EventWaitHandle,List<string>>)param;
Console.WriteLine(Thread.CurrentThread.Name + "执行开始");
//sleep线程,模拟查询业务
if (t.Item1 == )
{
Thread.Sleep();
t.Item3.Add("这是第0个线程添加的内容");
}
else if (t.Item1 == )
{
Thread.Sleep();
t.Item3.Add("这是第1个线程添加的内容");
}
else if (t.Item1 == )
{
Thread.Sleep();
t.Item3.Add("这是第2个线程添加的内容");
}
//将事件状态设置为有信号,从而允许一个或多个等待线程继续执行。
t.Item2.Set();
Console.WriteLine(Thread.CurrentThread.Name + "执行结束");
}
在等待句柄任务中执行查询,并将结果加入数据list中
最后在任务的最后(执行完成)将等待事件句柄对象Set(),这个方法将发出一个信号(暂时理解为通知WaitHandle当前的等待事件句柄执行完成)
作者:methodname
链接:https://www.jianshu.com/p/64670b155b1c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
Lock锁
lock是一种比较好用的简单的线程同步方式,它是通过为给定对象获取互斥锁来实现同步的。它可以保证当一个线程在关键代码段的时候,另一个线程不会进来,它只能等待,等到那个线程对象被释放,也就是说线程出了临界区。
public void Function()
{
object lockThis = new object ();
lock (lockThis)
{
// Access thread-sensitive resources.
}
}
lock关键字的用法和用途。
using System;
using System.Threading;
namespace ThreadSimple
{
internal class Account
{
int balance; //余额
Random r=new Random();
internal Account(int initial)
{
balance=initial;
}
internal int Withdraw(int amount) //取回、取款
{
if(balance<)
{
//如果balance小于0则抛出异常
throw new Exception("NegativeBalance");//负的 余额
}
//下面的代码保证在当前线程修改balance的值完成之前
//不会有其他线程也执行这段代码来修改balance的值
//因此,balance的值是不可能小于0的
lock(this)
{
Console.WriteLine("CurrentThread:"+Thread.CurrentThread.Name);
//如果没有lock关键字的保护,那么可能在执行完if的条件判断(成立)之后
//另外一个线程却执行了balance=balance-amount修改了balance的值
//而这个修改对这个线程是不可见的,所以可能导致这时if的条件已经不成立了
//但是,这个线程却继续执行 balance=balance-amount,所以导致balance可能小于0
if(balance>=amount)
{
Thread.Sleep();
balance=balance-amount;
return amount;
} else
{
return ;
//transactionrejected
}
}
}
internal void DoTransactions()//取款事务
{
for (int i = ; i < ; i++)
{
Withdraw(r.Next(-, ));
}
}
} internal class Test
{
static internal Thread[] threads=new Thread[];
public static void Main()
{
Account acc=new Account();
for(int i=;i<;i++)
{
Thread t=new Thread(new ThreadStart(acc.DoTransactions));
threads[i]=t;
}
for (int i = ; i < ; i++)
{
threads[i].Name = i.ToString();
}
for (int i = ; i < ; i++)
{
threads[i].Start();
Console.ReadLine();
}
}
}
}
C# 多线程的等待所有线程结束的更多相关文章
- CountDownLatch 多线程,等待所有线程结束
CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 主要方法 public CountDownLatch(int count); 构造 ...
- C# 多线程的等待所有线程结束 用 ManualResetEvent 控制
using System; using System.Collections.Generic; using System.Threading; namespace ConsoleApplication ...
- C# 多线程的等待所有线程结束的一个问题
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 3 ...
- Java多线程之以7种方式让主线程等待子线程结束
记一次主线程等待子线程结束的多种方法的学习 在学习多线程时,最开始遇到的问题其实是"计算子线程运行时间",写到最后发现本文和标题更为符合,但是仍然基于问题:"在主线程中获 ...
- java 多线程 Thread.join子线程结束父线程再运行;join(long):等待超时毫秒数
Join的使用 目的:当子线程运行结束后,父线程才能再继续运行 /** * @ClassName ThreadJoinExample * @projectName: object1 * @author ...
- Java Thread.join()详解--父线程等待子线程结束后再结束
目录(?)[+] 阅读目录 一.使用方式. 二.为什么要用join()方法 三.join方法的作用 join 四.用实例来理解 打印结果: 打印结果: 五.从源码看join()方法 join是Th ...
- Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束
Java 5 开始引入的 Concurrent 并发软件包里面的 CountDownLatch 其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是 ...
- 线程:Java主线程等待子线程结束
使用Thread.join()方法: public class App { public static void main(String[] args) { testMain(); } public ...
- Java如何等待子线程执行结束
工作中往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线 ...
随机推荐
- Mybatis自查询递归查找子菜单
之前写过 java从数据库读取菜单,递归生成菜单树 今天才发现mybatis也可以递归查询子菜单 先看一下数据库 主键id,名称name,父id,和url 设计菜单类 public class Men ...
- FastAdmin 自学教程 - 目录(持续更新)(2019-10-11)
FastAdmin 自学教程 - 目录 本自学教程将不定期更新. 了解 FastAdmin FastAdmin 开发第 1 天:了解 FastAdmin 框架 FastAdmin 开发第 2 天:安装 ...
- python 定义子类
- 洛谷2501 BZOJ1801中国象棋题解
题目链接 BZ链接 其实dp只要把状态想好后转移就很好写了(flag*1) f[i][j][k]表示到了第i行,有j列放了一个跑,有k列放了两个跑的方案总数 然后大力讨论,转移即可 # include ...
- 原生js实现复制文本到粘贴板
项目中经常会遇到点击按钮复制订单号.订单id等内容到粘贴板中的需求.可是通常我们都是用Ctrl + c或右击复制的,别操心,js也是有复制命令的,那就是document.execCommand('co ...
- 记一次Celery的仇
背景:项目在公司的一台虚拟机上运行(32核+32G).其他人的项目也在这台物理机上运行..我的训练代码是单进程的,跑完一次需要大约10h(数据量大逮着一个核使劲跑..):训练是一个Celery定时任务 ...
- sql —— top
用于规定要返回的记录的数目 原表: 我们如果只想看前三个学生信息的话:
- mysql把一个表的字段update成另一个表的字段根据id
mysql把一个表的字段update成另一个表的字段根据id 1.填充activity表里面的creator字段,用org的founderid,其中activity的orgid要和org的id对应,具 ...
- 前端知识---html
HTML HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏 ...
- Android 高仿QQ滑动弹出菜单标记已读、未读消息
在上一篇博客<Android 高仿微信(QQ)滑动弹出编辑.删除菜单效果,增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接 ...