• C#线程系列讲座(2):Thread类的应用


    作者:银河使者

    一、Thread 类的基本用法

    通过System.Threading.Thread类可以开始新的线程,并在线程堆栈中运行静态或者实例方法。可以通过Thread类得构造方法传递一个无参数,并且不返回值(返回void)的委托(ThreadStart),这个委托的定义如下:

    [ComVisibleAttribute(true)]

    public delegate void ThreadStart()

    我们可以通过如下的方法来建立并运行一个线程。

    A。静态方法
    using System;
    using
     System.Collections.Generic;
    using
     System.Linq;
    using
     System.Text;
    using
     System.Threading;

    namespace MyThread
    {
        
    class Program
        {
            
    public static void myStaticThreadMethod()
            {
                Console.WriteLine(
    "myStaticThreadMethod");
            }
            
    static void Main(string[] args)
            {
                Thread thread1 
    = new Thread(myStaticThreadMethod);
                thread1.Start();  
    // 只要使用Start方法,线程才会运行
            }
        }
    }
    除了运行静态的方法,还可以在线程中运行实例方法,代码如下:

    B. 实例方法

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;

    namespace MyThread
    {
        
    class Program
        {
            
    public void myThreadMethod()
            {
                Console.WriteLine(
    "myThreadMethod");
            }
            
    static void Main(string[] args)
            {
                Thread thread2 
    = new Thread(new Program().myThreadMethod);
                thread2.Start();
            }
        }
    }
    C. 匿名委托或者Lamdba表达式

    Thread thread3 = new Thread(delegate() { Console.WriteLine("匿名委托"); });
    thread3.Start();

    Thread thread4 
    = new Thread(( ) => { Console.WriteLine("Lambda表达式"); });
    thread4.Start();
    其中Lambda表达式前面的( )表示没有参数。

        为了区分不同的线程,还可以为Thread类的Name属性赋值,代码如下:

    Thread thread5 = new Thread(() => { Console.WriteLine(Thread.CurrentThread.Name); });
    thread5.Name 
    = "我的Lamdba";
    thread5.Start();

    二、为线程传递参数

    Thread类有一个带参数的委托类型的重载形式。这个委托的定义如下:

    [ComVisibleAttribute(false)]

    public delegate void ParameterizedThreadStart(Object obj)

    这个Thread类的构造方法的定义如下:

        public Thread(ParameterizedThreadStart start);

    下面的代码使用了这个带参数的委托向线程传递一个字符串参数:

    public static void myStaticParamThreadMethod(Object obj)
    {
        Console.WriteLine(obj);
    }

    static void Main(string[] args)
    {
          Thread thread 
    = new Thread(myStaticParamThreadMethod);
          thread.Start(
    "通过委托的参数传值");
    }

    要注意的是,如果使用的是不带参数的委托,不能使用带参数的Start方法运行线程,否则系统会抛出异常。但使用带参数的委托,可以使用thread.Start()来运行线程,这时所传递的参数值为null

    三、前台线程和后台线程

    使用Thread 建立的线程默认情况下都是前台线程,在进程中,只要有一个前台线程未退出,进程就不会终止。主线程就是一个前台线程。而后台线程不管线程是否结束,只要所有的前台线程都退出(包括正常退出和异常退出)后,进程就会自动终止。一般后台线程用于处理时间较短的任务,如在一个Web服务器中可以利用后台线程来处理客户端发过来的请求信息。而前台线程一般用于处理需要长时间等待的任务,如在Web服务器中的监听客户端的程序,或者是定时对某些系统资源进行扫描的程序。下面代码演示了前台线程和后台线程的区别。

     public static  void myfunction(object obj)
    {
    Thread.Sleep(
    3000);
    Console.WriteLine(obj);
    Console.ReadLine();
    }
    static void Main(string[] args)
    {
    Thread thread
    = new Thread(myfunction);
    //thread.IsBackground
    = true;
    thread.Start(
    "通过委托的参数传值");
    }

    如果运行上面的代码,程序会等待3秒后退出,如果将注释去掉,将thread设成后台线程,则程序会立即退出。

        要注意的是,必须在调用Start方法之前设置线程的类型,否则一但线程运行,将无法改变其类型。

        通过BeginXXX方法运行的线程都是后台线程。'

    四:判断多个线程是否都结束的两种方法

    确定所有的线程是否都完成了工作的方法有很多,如可以采用类似于对象计数器的方法,所谓对象计数器,就是一个对象被引用一次,这个计数器就加1,销毁引用就减1,如果引用数为0,则垃圾搜集器就会对这些引用数为0的对象进行回收。

    方法一:线程计数器。

    线程也可以采用计数器的方法,即为所有需要监视的线程设一个线程计数器,每开始一个线程,在线程的执行方法中为这个计数器加1,如果某个线程结束(在线程执行方法的最后为这个计数器减1),为这个计数器减1。然后再开始一个线程,按着一定的时间间隔来监视这个计数器,如是棕个计数器为0,说明所有的线程都结束了。当然,也可以不用这个监视线程,而在每一个工作线程的最后(在为计数器减1的代码的后面)来监视这个计数器,也就是说,每一个工作线程在退出之前,还要负责检测这个计数器。使用这种方法不要忘了同步这个计数器变量啊,否则会产生意想不到的后果。

        class ThreadCounter : MyThread
        {
            
    private static int count = 0
    ;
            
    private int
     ms;
            
    private static void
     increment()
            {
                
    lock (typeof(ThreadCounter))  // 必须同步计数器

                {
                    count
    ++
    ;
                }
            }
            
    private static void
     decrease()
            {
                
    lock (typeof
    (ThreadCounter))
                {
                    count
    --
    ;
                }
            }
            
    private static int
     getCount()
            {
                
    lock (typeof
    (ThreadCounter))
                {
                    
    return
     count;
                }
            }
            
    public ThreadCounter(int
     ms)
            {
                
    this.ms =
     ms;
            }
            
    override public void
     run()
            {
                increment();
                Thread.Sleep(ms);
                Console.WriteLine(ms.ToString()
    +"毫秒任务结束"
    );
                decrease();
                
    if (getCount() == 0
    )
                    Console.WriteLine(
    "所有任务结束"
    );
            }
        }


    ThreadCounter counter1 
    = new ThreadCounter(3000
    );
    ThreadCounter counter2 
    = new ThreadCounter(5000
    );
    ThreadCounter counter3 
    = new ThreadCounter(7000
    );

    counter1.start();
    counter2.start();
    counter3.start();

    方法二。

     class Program
    {
    private static void threadMethod(Object obj)
    {
    Thread.Sleep(Int32.Parse(obj.ToString()));
    Console.WriteLine(obj
    + "毫秒任务节结束");
    }
    private static void joinAllThread(Object obj)
    {
    Thread[] threads
    = obj as Thread[];
    foreach (Thread t in threads)
    t.Join();
    Console.WriteLine(
    "所有的线程结束");
    }
    static void Main(string[] args)
    {
    Thread thread1
    = new Thread(threadMethod);
    Thread thread2
    = new Thread(threadMethod);
    Thread thread3
    = new Thread(threadMethod);
    thread1.Start(
    3000);
    thread2.Start(
    5500);
    thread3.Start(
    8000);

    Thread joinThread
    = new Thread(joinAllThread);
    joinThread.Start(
    new Thread[] { thread1, thread2, thread3 });
    }

    }
  • 相关阅读:
    Python元组、列表、字典
    测试通过Word直接发布博文
    Python环境搭建(windows)
    hdu 4003 Find Metal Mineral 树形DP
    poj 1986 Distance Queries LCA
    poj 1470 Closest Common Ancestors LCA
    poj 1330 Nearest Common Ancestors LCA
    hdu 3046 Pleasant sheep and big big wolf 最小割
    poj 3281 Dining 最大流
    zoj 2760 How Many Shortest Path 最大流
  • 原文地址:https://www.cnblogs.com/huacw/p/2113010.html
Copyright © 2020-2023  润新知