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", 4321);  
newThread.start();

 

 

EventWaitHandle(等待事件句柄)

EventWaitHandle是一個在線程處理上的類,它可以和WaitHandle配合使用完成多線程任務等待調度,並且在主線程中統一處理想要的結果。

 

 private List<string> test()
        {
            List<string> list = new List<string>();
            //創建等待事件句柄集合
            var watis = new List<EventWaitHandle>();
            for (int i = 0; i < 5; 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 == 0)
            {
                Thread.Sleep(1500);
                t.Item3.Add("這是第0個線程添加的內容");
            }
            else if (t.Item1 == 1)
            {
                Thread.Sleep(1234);
                t.Item3.Add("這是第1個線程添加的內容");
            }
            else if (t.Item1 == 2)
            {
                Thread.Sleep(1759);
                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<0) 
            {  
                //如果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(5);
                    balance=balance-amount; 
                    return  amount; 
                }  else 
                { 
                    return 0;
                    //transactionrejected 
                } 
            }  
        }
        internal void DoTransactions()//取款事務
        {
            for (int i = 0; i < 100; i++)
            {
                Withdraw(r.Next(-50, 100));
            }
        }
    }  
 

    internal class Test  
    {  
        static internal Thread[] threads=new Thread[10]; 
        public static void Main()  
        {  
            Account acc=new Account(0); 
            for(int i=0;i<10;i++) 
            {  
                Thread t=new Thread(new ThreadStart(acc.DoTransactions));
                threads[i]=t; 
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].Name = i.ToString();
            }
            for (int i = 0; i < 10; i++)
            {
                threads[i].Start();
                Console.ReadLine();
            }
        }
    } 
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM