需求:成员A可能有几十个,我需要更新所有的A,然后根据A的数据,去更新成员B。

解决方案:思路是想通过多线程更新所有的A,然后通过等待线程来确定所有的A是否都更新完,最后更新B。

Member B = ....;//B成员的model
IList<Member> list = ......;//查出所有的A成员,装进list里。 ManualResetEvent[] manualEvents = new ManualResetEvent[list.Count];
//更新所有的A成员
for (int i = ; i < list.Count; i++)
{
manualEvents[i] = new ManualResetEvent(false);//初始化的ManualResetEvent必须是false
model = new te();//目前我只知道此处只能传一个参数,所以为了传递多个参数,我写了个model,然后把要参数都放进model里
model.MRevent = manualEvents[i];
model.member = list[i];//此处是我处理数据需要的参数,把成员的model传进去
ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateMember), model);
}
//等待所有线程执行完毕
WaitHandle.WaitAll(manualEvents); //更新B成员
model = new te();
model.member = B;
model.MRevent = new ManualResetEvent(false);
UpdateMember(model);

处理数据的方法

public void UpdateMember(object tsmodel)
{
te stateInfo = (te)tsmodel;
Member member = stateInfo.member;//中间为处理数据更新成员数据
...... stateInfo.MRevent.Set(); //将事件状态设置为终止状态,允许一个或多个等待线程继续(我个人理解是调用此方法,及为该线程结束,ManualResetEvent应该变成true)
}

新建立的model

public class te
{
public Member member{ get; set; }
public ManualResetEvent MRevent { get; set; }//小于64线程的时候使用
public MutipleThreadResetEvent MTRevent { get; set; }//大于64线程的时候使用
}

此处出现了新问题:

当线程大于64条时,会报错。应该是WaitHandle.WaitAll(manualEvents);这等待的线程数不能大于64。

错误信息:waithandles 的数目必须少于或等于 64 个。

经过网上查询,找到的解决办法,原文地址http://www.cnblogs.com/xiaofengfeng/archive/2012/12/27/2836183.html

原理:封装一个ManualResetEvent对象,一个计数器current,提供SetOne和WaitAll方法;

主线程调用WaitAll方法使ManualResetEvent对象等待唤醒信号;

各个子线程调用setOne方法 ,setOne每执行一次current减1,直到current等于0时表示所有子线程执行完毕 ,调用ManualResetEvent的set方法,这时主线程可以执行WaitAll之后的步骤。

目标:减少ManualResetEvent对象的大量产生和使用的简单性。

/********************************************************************************
* Copyright © 2001 - 2010Comit. All Rights Reserved.
* 文件:MutipleThreadResetEvent.cs
* 作者:杨柳
* 日期:2010年11月13日
* 描述:封装 ManualResetEvent ,该类允许一次等待N(N>64)个事件执行完毕
*
* 解决问题:WaitHandle.WaitAll(evetlist)方法最大只能等待64个ManualResetEvent事件
* *********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace TestMutipleThreadRestEvent
{
/// <summary>
/// 封装ManualResetEvent
/// </summary>
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) == )
{
//当所以等待线程执行完毕时,唤醒等待的线程
done.Set();
}
} /// <summary>
/// 等待所以线程执行完毕
/// </summary>
public void WaitAll()
{
done.WaitOne();
} /// <summary>
/// 释放对象占用的空间
/// </summary>
public void Dispose()
{
((IDisposable)done).Dispose();
}
} }

本质就是只通过1个ManualResetEvent 对象就可以实现同步N(N可以大于64)个线程

修改后的方法:(黄色荧光笔的都是改动的代码)

Member B = ....;//B成员的model
IList<Member> list = ......;//查出所有的A成员,装进list里。
//更所有A成员
using (var countdown = new MutipleThreadResetEvent(list.Count))
{
for (int i = ; i < list.Count; i++)
{
model = new te();
model.MTRevent = countdown;
model.member = list[i];
//开启N个线程,传递MutipleThreadResetEvent对象给子线程
ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateMember), model);
} //等待所有线程执行完毕
countdown.WaitAll();
}
//更新B成员
using (var countdown = new MutipleThreadResetEvent())
{
model = new te();
model.MTRevent = countdown;
model.member = B;
//开启N个线程,传递MutipleThreadResetEvent对象给子线程
ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateMember), model);
//等待所有线程执行完毕
countdown.WaitAll();
}

处理数据的方法需要小改一下:

public void UpdateMember(object tsmodel)
{
te stateInfo = (te)tsmodel;
Member member = stateInfo.member;
//中间为处理数据更新成员数据
...... stateInfo.MTRevent.SetOne();//此处调用封装的方法
}

此时,大于64条线程的可以使用了。

C# 多线程ManualResetEvent、等待所有线程的更多相关文章

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

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

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

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

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

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

  4. 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 ...

  5. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  6. c/c++ 多线程 多个线程等待同一个线程的一次性事件

    多线程 多个线程等待一个线程的一次性事件 背景:从多个线程访问同一个std::future,也就是多个线程都在等待同一个线程的结果,这时怎么处理. 办法:由于std::future只能被调用一次get ...

  7. “全栈2019”Java多线程第三十七章:如何让等待的线程无法被中断

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  8. “全栈2019”Java多线程第三十四章:超时自动唤醒被等待的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  9. 多线程threading初识,线程等待

    1.线程是程序里面最小的执行单元. 2.进程是资源的集合. 线程是包含在进程里面的,一个进程可以有多个线程,但只要要有一个线程. 一.多线程,就是N个线程一起干活: 1.传统方式,串行,循环5次需要1 ...

随机推荐

  1. 关于golang中包(package)的二三事儿

    golang的package和其他语言的组织方式完全不同,刚开始接触时,很不适应. golang的package的特点: 1.go的package不局限于一个文件,可以由多个文件组成. 组成一个pac ...

  2. selenium 如何处理table

    qi_ling2005  http://jarvi.iteye.com/blog/1477837 andyguo  http://blog.csdn.net/gzh0222/article/detai ...

  3. Java编程思想学习笔记——初始化与清理

    初始化 构造器保证初始化 构造器采用与类相同的名称. 默认构造器(default constructor):不接受任何参数的构造器,也叫无参构造器. 构造器也能带有形式参数,就能在初始化对象时提供实际 ...

  4. 对事件委托绑定click的事件的解绑

    大家都知道解绑事件的jquery写法,很简单: $("xxx").unbind("click"); 然后对于事件委托式的事件绑定,亲测,这种解绑方法是无效的, ...

  5. MathType让矩阵中的小数以小数点对齐的教程

    用MathType编辑公式时,有很多模板都可以应用,并且这些模板并不是只有一种用途,比如矩阵.矩阵模板可以用来编辑矩阵也可是用来编辑一些需要排列组合的数据等等.在用MathType编辑矩阵时,如果里面 ...

  6. 改造phpcms-v9自带的字符串截取函数

    1.phpcms-v9自带的字符串截取函数在phpcms/libs/functions/global.func.php文件中: /** * 字符截取 支持UTF8/GBK * @param $stri ...

  7. ios利用Reachability确认网络环境3G/WIFI(转)

    iPhone开发技巧之网络篇(4)--- 确认网络环境  开发Web等网络应用程序的时候,需要确认网络环境,连接情况等信息.如果没有处理它们,是不会通过Apple的审查的. Apple 的 例程 Re ...

  8. 【代码审计】iCMS_v7.0.7 search.admincp.php页面存在SQL注入漏洞

      0x00 环境准备 iCMS官网:https://www.icmsdev.com 网站源码版本:iCMS-v7.0.7 程序源码下载:https://www.icmsdev.com/downloa ...

  9. PHPMailer命令执行及任意文件读取漏洞

    今天在thinkphp官网闲逛,无意下载了一套eduaskcms,查看了一下libs目录中居然存在PHPMailer-5.2.13,想起了之前看到的PHPMailer的漏洞,可惜这套CMS只提供了一个 ...

  10. Google TensorFlow 机器学习框架介绍和使用

    TensorFlow是什么? TensorFlow是Google开源的第二代用于数字计算(numerical computation)的软件库.它是基于数据流图的处理框架,图中的节点表示数学运算(ma ...