zoukankan      html  css  js  c++  java
  • 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配合使用完成多线程任务等待调度,并且在主线程中统一处理想要的结果。

                List<string> lst = new List<string>();
                //创建等待事件句柄集合
                var watis = new List<EventWaitHandle>();
                for (int t = 0; t < 3; t++)
                {
                    var handler = new ManualResetEvent(false);   //创建句柄   true终止状态
                    watis.Add(handler);                          // 添加EventWaitHandle对象
                    
                    //线程传入参数配置,这里定义了3个参数
                    var tup = new Tuple<object, List<string>, EventWaitHandle>(t, lst, handler);
    
                    /*创建线程,传入线程参数*/
                    Thread thfor = new Thread((object obj) =>
                    {
                        Tuple<object, List<string>, EventWaitHandle> tupitm = (Tuple<object, List<string>, EventWaitHandle>)obj;                    
                        object Wdt = tupitm.Item1;          //传入的第一个参数 【Item1】
                        tupitm.Item2.Add("返回字符串");     //传入的第二个参数 【Item3】                  
                        tupitm.Item3.Set();                 //传入的第二个参数 【Item2】   
                    });
                    //启动线程
                    thfor.Start(tup);
                }
                //等待句柄
                WaitHandle.WaitAll(watis.ToArray());
    • 首先创建了一个EventWaitHandle的list,这个list将用于来添加所有的需要执行的等待事件句柄

    • 然后将需要参与等待的任务(一个方法)参数化传入线程初始化的构造

    • 在线程启动时,将与之对应的EventWaitHandle子类ManualResetEvent的对象传入需要调用的任务(方法)中

    • 最后使用WaitHandle.WaitAll执行所有的等待事件句柄

    • 在等待句柄任务中执行查询,并将结果加入数据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();
                }
            }
        } 
    }
  • 相关阅读:
    C语言不定参数
    C和C++中的不定参数
    C/C++ 中头文件相互包含引发的问题
    Makefile经典教程(掌握这些足够)
    C语言中volatile关键字的作用
    C++中字符数组与string的相互转换
    C++中 使用数组作为map容器VAlue值的解决方法
    sql 内连接、外连接、自然连接等各种连接
    网站小图标
    Eclipse:快捷
  • 原文地址:https://www.cnblogs.com/lanyubaicl/p/11033120.html
Copyright © 2011-2022 走看看