向线程传递数据

  • 如果你想往线程的启动方法里传递参数,最简单的方式就是使用lambda表达式,在里面使用参数调用方法。 ```csharp using System; using System.Threading;

namespace ThreadTest { class Program { static void Main() { new Thread(() => Print(“Hello World!”)).Start(); }

  1. static void Print(string message)
  2. {
  3. Console.WriteLine(message);
  4. }
  5. }

}

  1. - 甚至可以把整个逻辑都放在lambda里面。
  2. ```csharp
  3. using System;
  4. using System.Threading;
  5. namespace ThreadTest
  6. {
  7. class Program
  8. {
  9. static void Main()
  10. {
  11. new Thread(() =>
  12. {
  13. Console.WriteLine("Hello World!");
  14. Console.WriteLine("Hi~");
  15. }).Start();
  16. }
  17. }
  18. }

向线程传递数据在C#3.0之前

  • 在C#3.0之前,没有lambda表达式。可以使用Thread的Start方法来传递参数。 ```csharp using System; using System.Threading;

namespace ThreadTest { class Program { static void Main() { new Thread(Print).Start(“Hello World!”); }

  1. static void Print(object message) // object类型
  2. {
  3. Console.WriteLine(message.ToString());
  4. }
  5. }

}

  1. - Thread的重载构造函数可以接受下列两个委托之一作为参数:
  2. - `public delegate void ThreadStart();`
  3. - `public dalegate void ParameterizedThreadStart(object obj)`
  4. <a name="2ea23"></a>
  5. ## Lambda表达式与被捕获的变量
  6. - 使用Lambda表达式可以很简单的给Thread传递参数。但是线程开始后,可能会不小心修改了被捕获的变量,这要多加注意。
  7. ```csharp
  8. using System;
  9. using System.Threading;
  10. namespace ThreadTest
  11. {
  12. class Program
  13. {
  14. static void Main()
  15. {
  16. for (int i = 0; i < 10; i++)
  17. {
  18. new Thread(() => Console.Write(i)).Start();
  19. }
  20. }
  21. // i 在循环的整个生命周期内指向的是同一个内存地址
  22. // 每个线程对Console.WriteLine()的调用都会在它运行的时候进行修改。
  23. }
  24. }
  • 解决方案(但是顺序还是无法保证) ```csharp using System; using System.Threading;

namespace ThreadTest { class Program { static void Main() { for (int i = 0; i < 10; i++) { int temp = i; new Thread(() => Console.Write(temp)).Start(); } }

  1. // 顺序仍然无法保证
  2. }

}

  1. <a name="9f65u"></a>
  2. ## 异常处理
  3. - 创建线程时在作用范围内的try/catch/finally块,在线程开始执行后就与线程无关了。
  4. ```csharp
  5. using System;
  6. using System.Threading;
  7. namespace ThreadTest
  8. {
  9. class Program
  10. {
  11. static void Main()
  12. {
  13. try
  14. {
  15. new Thread(Go).Start();
  16. }
  17. catch (Exception e)
  18. {
  19. // 从不执行到这
  20. Console.WriteLine("Exception!" + e.Message);
  21. }
  22. }
  23. static void Go()
  24. {
  25. throw new NullReferenceException();
  26. }
  27. // 补救方法就是把异常处理放在Go方法里面
  28. }
  29. }
  30. -------------------------------------------处理------------------
  31. using System;
  32. using System.Threading;
  33. namespace ThreadTest
  34. {
  35. class Program
  36. {
  37. static void Main()
  38. {
  39. new Thread(Go).Start();
  40. }
  41. static void Go()
  42. {
  43. try
  44. {
  45. throw new NullReferenceException();
  46. }
  47. catch (Exception e)
  48. {
  49. Console.WriteLine("Exception!" + e.Message);
  50. }
  51. }
  52. }
  53. }
  • 在WPF、WinForm里,可以订阅全局异常处理事件:
    • Application.DispatcherUnhandleException
    • Application.ThreadException
    • 触发:在通过消息循环调用的程序的任何部分发生未处理的异常(这相当于应用程序处于活动状态时,在主线程上运行的所有代码)后,将触发这些异常。
    • 但是非UI线程上的未处理异常,并不会触发它。
  • 而任何线程有任何未处理的异常都会触发
    • AppDomain.CurrentDomain.UnhandleException