• C# 第八章『多线程』◆第3节:线程的方法


            一、启动线程

            通过提供一个委托来启动线程,该委托表示线程在其类构造函数中执行的方法。 然后调用 Start 方法以开始执行。

            构造函数可以使用两种委托类型之一,具体取决于是否可以将参数 Thread 传递给要执行的方法:

             如果方法没有参数,则向 ThreadStart 构造函数传递委托。 它具有签名:

    public delegate void ThreadStart()  

            如果方法具有参数,则向 ParameterizedThreadStart 构造函数传递委托。 它具有签名: 

    public delegate void ParameterizedThreadStart(object obj)  

            在C#中创建线程时,首先需要创建一个Thread委托实例,再以这个TreadStart委托作为参数,来构造Thread实例。

            二、Thread 构造函数

            Thread类拥有四种重载的构造函数:

    Thread(ParameterizedThreadStart)初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托。
    Thread(ThreadStart)初始化 Thread 类的新实例。
    Thread(ParameterizedThreadStart, Int32)初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托,并指定线程的最大堆栈大小。
    Thread(ThreadStart, Int32)初始化 Thread 类的新实例,指定线程的最大堆栈大小。

            注意:线程不会在创建时开始执行。 若要计划线程的执行,请调用 Start 方法。 若要将数据对象传递给线程,请使用 Start(Object) 方法重载

            备注:如果线程已经终止,则无法通过再次调用Start方法来重启线程。

            1、Thread(ParameterizedThreadStart)

    1. 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托。
    2. //未使用命名空间时,使用方法
    3. public Thread (System.Threading.ParameterizedThreadStart start);
    4. //使用了命名空间时,使用方法
    5. using System.Threading;
    6. public Thread (ParameterizedThreadStart start);

     案例:

    1. using System;
    2. using System.Threading;
    3. public class Work
    4. {
    5. public static void Main()
    6. {
    7. // 启动一个调用参数化静态方法的线程。
    8. Thread newThread = new Thread(Work.DoWork);
    9. newThread.Start(42);
    10. // 启动一个调用参数化实例方法的线程。
    11. Work w = new Work();
    12. newThread = new Thread(w.DoMoreWork);
    13. newThread.Start("The answer.");
    14. }
    15. public static void DoWork(object data)
    16. {
    17. Console.WriteLine("静态方法!. Data='{0}'",data);
    18. }
    19. public void DoMoreWork(object data)
    20. {
    21. Console.WriteLine("实例方法!. Data='{0}'",data);
    22. }
    23. }

            2、Thread(ThreadStart)

    1. //未使用命名空间
    2. public Thread (System.Threading.ThreadStart start);
    3. //使用了命名空间
    4. using System.Threading;
    5. public Thread (ThreadStart start);

            举例:创建执行静态方法的线程:

    1. using System;
    2. using System.Threading;
    3. class Test
    4. {
    5. static void Main()
    6. {
    7. Thread Nt1 =new Thread(new ThreadStart(Work.DoWork));
    8. Nt1.Start();
    9. }
    10. }
    11. class Work
    12. {
    13. public static void DoWork()
    14. {
    15. Console.WriteLine("新的线程启动(静态方法)");
    16. }
    17. }

             举例:创建执行实例方法的线程:

    1. using System;
    2. using System.Threading;
    3. class Test
    4. {
    5. static void Main()
    6. {
    7. Work Nw1 = new Work();
    8. Thread Nt1 =new Thread(new ThreadStart(Nw1.DoWork));
    9. Nt1.Start();
    10. }
    11. }
    12. class Work
    13. {
    14. public void DoWork()
    15. {
    16. Console.WriteLine("新的线程启动(实例方法)");
    17. }
    18. }

            找错误案例:

             正确修改为:

    1. using System;
    2. using System.Threading;
    3. class Test
    4. {
    5. static void Main()
    6. {
    7. Test x1 = new Test();
    8. Thread x2 = new Thread(new ThreadStart(x1.DoWork));
    9. x2.Start();
    10. }
    11. public void DoWork()
    12. {
    13. Console.WriteLine("新的线程启动(实例方法)");
    14. }
    15. }

            3、Thread(ParameterizedThreadStart, Int32)

            4、Thread(ThreadStart, Int32)

            三、线程休眠—Thread.Sleep 方法:将当前线程挂起指定的时间。

            线程的休眠是通过Thread类的Sleep方法实现的,而Thread类的实例的IsAlive属性可以判断线程是否执行完毕。

            Sleep方法有两种重载方式:

    Sleep(Int32)将当前线程挂起指定的毫秒数。
    Sleep(TimeSpan)将当前线程挂起指定的时间。

            注意:不要在主线程使用!

            1、Sleep(Int32):将当前线程挂起指定毫秒数,C#语法格式如下:

    public static void Sleep (int millisecondsTimeout);
    

            millisecondsTimeout:Int32,挂起线程的毫秒数。 如果 millisecondsTimeout 参数的值为零,则该线程会将其时间片的剩余部分让给任何已经准备好运行的、具有同等优先级的线程。 如果没有其他已经准备好运行的、具有同等优先级的线程,则不会挂起当前线程的执行。

    1. using System;
    2. using System.Threading;
    3. class Example
    4. {
    5. static void Main()
    6. {
    7. for (int i = 0; i < 5; i++)
    8. {
    9. Console.WriteLine("休眠 2 秒.");
    10. Thread.Sleep(2000);
    11. }
    12. Console.WriteLine("Main thread exits.");
    13. }
    14. }

            2、Sleep(TimeSpan):将当前线程挂起指定的时间,语法格式如下:

    public static void Sleep (TimeSpan timeout);

            timeout:挂起线程的时间量。 如果 timeout 参数的值为零,则该线程会将其时间片的剩余部分让给任何已经准备好运行的、具有同等优先级的线程。 如果没有其他已经准备好运行的、具有同等优先级的线程,则不会挂起当前线程的执行。

    1. 将当前线程挂起指定的时间:多少小时,多少分钟,多少秒
    2. public TimeSpan(int hours, int minutes, int seconds);
    1. using System;
    2. using System.Threading;
    3. class Example
    4. {
    5. static void Main()
    6. {
    7. TimeSpan interval = new TimeSpan(0, 0, 2);//0小时0分钟2秒
    8. for (int i = 0; i < 5; i++)
    9. {
    10. Console.WriteLine("Sleep for 2 seconds.");
    11. Thread.Sleep(interval);
    12. }
    13. Console.WriteLine("Main thread exits.");
    14. }
    15. }

            四、终止线程—Abort方法

            当一个线程执行时间太长时,用户有可能要终止这个线程,这个就要使用Abort方法。该方法有两种重载方式:

    Abort()在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。 调用此方法通常会终止线程。
    Abort(Object)引发在其上调用的线程中的 ThreadAbortException 以开始处理终止线程,同时提供有关线程终止的异常信息。 调用此方法通常会终止线程。

            备注:线程的Abort方法用于永久地停止托管线程。在调用Abort方法时,公共语言运行库在目标线程中引发ThreadAbortException异常,目标线程可捕捉此异常。一旦线程终止,将无法重新启动。

    1. 在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。 调用此方法通常会终止线程。
    2. public void Abort ();
    3. 引发在其上调用的线程中的 ThreadAbortException 以开始处理终止线程,同时提供有关线程终止的异常信息。 调用此方法通常会终止线程。
    4. public void Abort(Object stateInfo)
    5. stateInfo:一个对象,它包含应用程序特定的信息(如状态),该信息可供正被中止的线程使用。
    1. using System;
    2. using System.Threading;
    3. class Test
    4. {
    5. public static void Main()
    6. {
    7. Thread newThread = new Thread(new ThreadStart(TestMethod));
    8. newThread.Start();
    9. Thread.Sleep(1000);
    10. // Abort newThread.
    11. Console.WriteLine("Main aborting new thread.");
    12. newThread.Abort("Information from Main.");
    13. // Wait for the thread to terminate.
    14. newThread.Join();
    15. Console.WriteLine("New thread terminated - Main exiting.");
    16. }
    17. static void TestMethod()
    18. {
    19. try
    20. {
    21. while (true)
    22. {
    23. Console.WriteLine("New thread running.");
    24. Thread.Sleep(1000);
    25. }
    26. }
    27. catch (ThreadAbortException abortException)
    28. {
    29. Console.WriteLine((string)abortException.ExceptionState);
    30. }
    31. }
    32. }

            五、线程的加入 —Join方法:在此实例表示的线程终止前,阻止调用线程。

            Join方法用来阻塞调用线程,直到某个线程终止为止。该方法有三种重载形式:

    Join()在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止。
    Join(Int32)在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止或经过了指定时间为止。
    Join(TimeSpan)在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止或经过了指定时间为止。

             备注:如果在程序中使用了多线程,辅助线程还没有执行完毕,那么在关闭窗体时,必须要关闭辅助线程,否则会引发异常。

            ① Join()

    1. 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止。
    2. public void Join ();
    3. Join 是一种同步方法,它阻止调用 (线程,即调用方法的线程) 调用方法的线程 Join 完成。
    4. 使用此方法可确保线程已终止。
    5. 如果线程未终止,调用方将无限期阻止。
    6. 在下面的示例中,线程调用 的 方法 Thread1 Join() Thread2 ,这会导致 Thread1 在 Thread2 完成后阻止。
    1. using System;
    2. using System.Threading;
    3. public class Example
    4. {
    5. static Thread thread1, thread2;
    6. public static void Main()
    7. {
    8. thread1 = new Thread(ThreadProc);
    9. thread1.Name = "Thread1";
    10. thread1.Start();
    11. thread2 = new Thread(ThreadProc);
    12. thread2.Name = "Thread2";
    13. thread2.Start();
    14. }
    15. private static void ThreadProc()
    16. {
    17. Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
    18. if (Thread.CurrentThread.Name == "Thread1" &&
    19. thread2.ThreadState != ThreadState.Unstarted)
    20. thread2.Join();
    21. Thread.Sleep(4000);
    22. Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
    23. Console.WriteLine("Thread1: {0}", thread1.ThreadState);
    24. Console.WriteLine("Thread2: {0}\n", thread2.ThreadState);
    25. }
    26. }

            时线程已终止 Join ,则该方法将立即返回 。

            ②Join(Int32)

    1. 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止或经过了指定时间为止。
    2. public bool Join (int millisecondsTimeout);
    3. 参数:millisecondsTimeout—等待线程终止的毫秒数。
    4. 如果线程已终止,则为 true;如果 false 参数指定的时间量已过之后还未终止线程,则为 millisecondsTimeout。
    1. using System;
    2. using System.Threading;
    3. public class Example
    4. {
    5. static Thread thread1, thread2;
    6. public static void Main()
    7. {
    8. thread1 = new Thread(ThreadProc);
    9. thread1.Name = "Thread1";
    10. thread1.Start();
    11. thread2 = new Thread(ThreadProc);
    12. thread2.Name = "Thread2";
    13. thread2.Start();
    14. }
    15. private static void ThreadProc()
    16. {
    17. Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
    18. if (Thread.CurrentThread.Name == "Thread1" &&
    19. thread2.ThreadState != ThreadState.Unstarted)
    20. if (thread2.Join(2000))
    21. Console.WriteLine("Thread2 has termminated.");
    22. else
    23. Console.WriteLine("The timeout has elapsed and Thread1 will resume.");
    24. Thread.Sleep(4000);
    25. Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
    26. Console.WriteLine("Thread1: {0}", thread1.ThreadState);
    27. Console.WriteLine("Thread2: {0}\n", thread2.ThreadState);
    28. }
    29. }

            ③Join(TimeSpan)

    1. 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻止调用线程,直到由该实例表示的线程终止或经过了指定时间为止。
    2. public bool Join (TimeSpan timeout);
    3. timeout:设置等待线程终止的时间量的TimeSpan。
    4. 如果线程已终止,则为 true;如果 false 参数指定的时间量已过之后还未终止线程,则为 timeout。
    1. //下面的代码示例演示如何将 值 TimeSpan 与 方法 Join 一起使用。
    2. using System;
    3. using System.Threading;
    4. class Test
    5. {
    6. static TimeSpan waitTime = new TimeSpan(0, 0, 1);
    7. public static void Main()
    8. {
    9. Thread newThread = new Thread(Work);
    10. newThread.Start();
    11. if(newThread.Join(waitTime + waitTime)) {
    12. Console.WriteLine("New thread terminated.");
    13. }
    14. else {
    15. Console.WriteLine("Join timed out.");
    16. }
    17. }
    18. static void Work()
    19. {
    20. Thread.Sleep(waitTime);
    21. }
    22. }

             备注:Join(TimeSpan) 是一种同步方法,它阻止调用线程 (,即调用方法) 直到调用方法的线程已完成或已过时间间隔 Join 。

    1. //下面的示例中,线程调用 的 方法,这会导致 阻塞,直到已完成或 Thread1 Join() Thread2 Thread1 Thread2 2 秒已过。
    2. using System;
    3. using System.Threading;
    4. public class Example
    5. {
    6. static Thread thread1, thread2;
    7. public static void Main()
    8. {
    9. thread1 = new Thread(ThreadProc);
    10. thread1.Name = "Thread1";
    11. thread1.Start();
    12. thread2 = new Thread(ThreadProc);
    13. thread2.Name = "Thread2";
    14. thread2.Start();
    15. }
    16. private static void ThreadProc()
    17. {
    18. Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
    19. if (Thread.CurrentThread.Name == "Thread1" &&
    20. thread2.ThreadState != ThreadState.Unstarted)
    21. if (thread2.Join(TimeSpan.FromSeconds(2)))
    22. Console.WriteLine("Thread2 has termminated.");
    23. else
    24. Console.WriteLine("The timeout has elapsed and Thread1 will resume.");
    25. Thread.Sleep(4000);
    26. Console.WriteLine("\nCurrent thread: {0}", Thread.CurrentThread.Name);
    27. Console.WriteLine("Thread1: {0}", thread1.ThreadState);
    28. Console.WriteLine("Thread2: {0}\n", thread2.ThreadState);
    29. }
    30. }

            如果 Timeout.Infinite 为 指定了 ,则此方法的行为与方法重载相同, timeout 返回值 Join() 除外。

            如果调用 时线程已终止 Join ,则该方法将立即返回 。

            此方法更改当前线程的状态以包括 WaitSleepJoin 。 不能对 Join 状态为 的线程 ThreadState.Unstarted 调用 。

            六、线程的挂起与恢复(新版本已弃用)

            Suspend方法用于挂起线程,Resume方法用于继续执行已经挂起的线程。可以使用这两个方法进行线程的同步,和Start方法有些类似的是:在调用Suspend方法后不会立即停止,而是执行到一个安全点后挂起。

            1、Suspend方法

            挂起线程,或者如果线程已挂起,则不起作用。语法格式为:

    public void Suspend();

            2、Resume方法

            继续已挂起的线程。语法格式为:

    public void Resumne();
    
  • 相关阅读:
    探索银行的的IT架构
    OpenCV入门3:像素操作
    使用wxPython和PyMuPDF合并PDF文档并自动复制到剪贴板
    Thrift RPC改进—更加准确的超时管理
    经纬高到北东天的坐标相互转换matlab
    人脸动作迁移——基于DaGAN深度感知的生成对抗网络操作对口型数字人
    mybatis缓存-二级缓存
    simulink代码生成
    vertx的学习总结6
    【1day】H5S视频平台未授权漏洞学习
  • 原文地址:https://blog.csdn.net/qq_45336030/article/details/126483194