1. 程式人生 > >C# 多執行緒ManualResetEvent、等待所有執行緒

C# 多執行緒ManualResetEvent、等待所有執行緒

需求:成員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 = 0; 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 個。

原理:封裝一個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) == 0)
            {
                //當所以等待執行緒執行完畢時,喚醒等待的執行緒
                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 = 0; 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(1))
{
    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等待所有執行

需求:成員A可能有幾十個,我需要更新所有的A,然後根據A的資料,去更新成員B。 解決方案:思路是想通過多執行緒更新所有的A,然後通過等待執行緒來確定所有的A是否都更新完,最後更新B。 Member B = ....;//B成員的model IList<Member> list = .

Java執行等待所有執行結束(CountDownLatch/CyclicBarrier)

本文主要是參考官方文件做一學習用途。 官方連結: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html http://docs.oracle.com/javase/1.5.0/docs/a

Linux執行---執行建立等待分離優先順序

建立執行緒,等待執行緒終止 #include <stdio.h> #include <pthread.h> #include <stdlib.h> void f(void) { for(int i=0; i&l

java中等待所有執行執行結束

  看過之後在想java中有很大的靈活性,應該有更多的方式可以做這件事。   這個事情的場景是這樣的:許多執行緒並行的計算一堆問題,然後每個計算存在一個佇列,在主執行緒要等待所有計算結果完成後排序並展示出來。這樣的問題其實很常見。   1. 使用join。這種方式其實並不

自定義執行內建執行池.md

自定義簡單執行緒池 python執行緒是可以重複利用的,如果呼叫的時候每次都建立一個執行緒,則太浪費資源了 我把多執行緒比作服務員,每次有客人來的時候,都分配一個專門的服務員去服務; 當客人走了之後,服務員回到空閒狀態,繼續等待新的客人 import threa

top 執行一次顯示所有程序資訊

1、執行一次 top命令會動態顯示資訊,若需要靜態的,比如只執行一次,或者只需要關於CPU的分析的那幾行,則使用代以下引數的命令: top -n 1 top執行一次,這樣便可以很方便的取出資訊,比如把這個資訊存到一個檔案中。 top -n 1 | head -n 5

[C++]個物件構造析構構造和析構的順序

#include <iostream>//多個物件構造和析構//1)當類中有成員變數是其它類的物件時,首先呼叫成員變數的建構函式,呼叫順序與宣告順序相同;//之後呼叫自身類的建構函式//2)解構函式的呼叫順序與對應的建構函式呼叫順序相反////2、類成員中若有const修飾,必須在物件初始化的時候

使用執行池時讓所有執行執行完再進行下一步

    我們知道,當不使用執行緒池時,想讓A執行緒在B執行緒執行完之後執行,需要在A中的某個呼叫處,呼叫B.join,但如果使用jdk1.5以後提供的執行緒池ExecutorService,這個就用不上了,用了會出同步問題,其實這個場景應該是很常見的吧,比如你用多執行緒併發執

C#執行基礎(執行的優先順序狀態同步)

一、關於多執行緒的優先順序、狀態、同步指令碼如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System

C# 執行學習系列四之取消超時子執行操作

1、簡介 雖然ThreadPool、Thread能開啟子執行緒將一些任務交給子執行緒去承擔,但是很多時候,因為某種原因,比如子執行緒發生異常、或者子執行緒的業務邏輯不符合我們的預期,那麼這個時候我們必須關閉它,而不是讓它繼續執行,消耗資源.讓CPU不在把時間和資源花在沒有意義的程式碼上.  

c/c++ 執行 等待一次性事件 packaged_task用法

多執行緒 等待一次性事件 packaged_task用法 背景:不是很明白,不知道為了解決什麼業務場景,感覺std::asynck可以優雅的搞定一切,一次等待性事件,為什麼還有個packaged_task。 用法:和std::async一樣,也能夠返回std::future,通過呼叫get_future方

c/c++ 執行 等待一次性事件 std::promise用法

多執行緒 等待一次性事件 std::promise用法 背景:不是很明白,不知道為了解決什麼業務場景,感覺std::async可以優雅的搞定一切的一次等待性事件,為什麼還有個std::promise。 用法:和std::async一樣,也能夠返回std::future,通過呼叫get_future方法。也

c/c++ 執行 執行等待同一個執行的一次性事件

多執行緒 多個執行緒等待一個執行緒的一次性事件 背景:從多個執行緒訪問同一個std::future,也就是多個執行緒都在等待同一個執行緒的結果,這時怎麼處理。 辦法:由於std::future只能被呼叫一次get方法,也就是隻能被某一個執行緒等待(同步)一次,不支援被多個執行緒等待。所以std::shar

C# 基礎(十四)C#單例模式:首先介紹 單執行執行加鎖 單例模式。然後介紹單例模式的執行同步:執行有序訪問共享記憶體。

一、簡介 本篇文章將介紹如何使用單例模式,也就是類的例項化,在整個專案的生命週期內,只例項化一次。在單例模式中,往往可以看到如SourceCode.cs:這樣的結構的。 SourceCode.cs: public class Singleton { private static

Java第十四天學習筆記~執行執行直接通訊---等待喚醒機制生產者消費者問題JDK1.5新特性wait和sleep區別)

執行緒直接通訊示例 //資源 class Resource { String name; String sex; } //輸入 class Input implements Runnable { Resource r; Input(Resource r) { this.r=r;

GCD執行工併發等待所有任務完成

在實際專案中我們經常會遇到,發出多個網路請求,然後等待所有結果都返回後,再進行下一步操作的需求。那麼GCD完美的解決了這個樣的需求。 第一種方式: //建立佇列組 dispatch_g

Windows10 VS2017 C++執行傳參和等待執行結束

#include "pch.h" #include <iostream> #include <windows.h> using namespace std; typedef struct MyData { const char* str; }MYDATA;

C++執行程式設計學習(1)】-CPU個數CPU核心數CPU執行

轉自:CPU個數、CPU核心數、CPU執行緒數(by kimsimple)   CPU個數即CPU晶片個數。 CPU核心數是指物理上,也就是硬體上存在著幾個核心。比如,雙核就是包括2個相對獨立的CPU核心單元組,四核就包含4個相對獨立的CPU核心單元組。 CPU執行緒數是一

C++——執行程式設計(二)std::mutex 執行同步解決資源競爭問題

前言 執行緒同步 這裡的“同”不是同時、一起執行的意思,而是指協同、協助、互相配合。執行緒同步是指多個執行緒協同步調,按預定的先後次序進行執行。 執行緒A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B執行;B依言執行,再將結果給A;

Objective-C執行詳解(NSThreadNSOperationGCD)

程序和執行緒 程式:一個由原始碼生成的可執行應用(比如qq,微信…) 程序:程序是指在系統中正在執行的一個應用程式。一個正在執行的程式可以看成一個程序,程序負責去向手機系統申請資源,同時將這些資源排程給我們的執行緒 執行緒:1個程序要想執行任務,必須得有執