向线程传递数据
- 如果你想往线程的启动方法里传递参数,最简单的方式就是使用lambda表达式,在里面使用参数调用方法。 ```csharp using System; using System.Threading;
namespace ThreadTest { class Program { static void Main() { new Thread(() => Print(“Hello World!”)).Start(); }
static void Print(string message){Console.WriteLine(message);}}
}
- 甚至可以把整个逻辑都放在lambda里面。```csharpusing System;using System.Threading;namespace ThreadTest{class Program{static void Main(){new Thread(() =>{Console.WriteLine("Hello World!");Console.WriteLine("Hi~");}).Start();}}}
向线程传递数据在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!”); }
static void Print(object message) // object类型{Console.WriteLine(message.ToString());}}
}
- Thread的重载构造函数可以接受下列两个委托之一作为参数:- `public delegate void ThreadStart();`- `public dalegate void ParameterizedThreadStart(object obj)`<a name="2ea23"></a>## Lambda表达式与被捕获的变量- 使用Lambda表达式可以很简单的给Thread传递参数。但是线程开始后,可能会不小心修改了被捕获的变量,这要多加注意。```csharpusing System;using System.Threading;namespace ThreadTest{class Program{static void Main(){for (int i = 0; i < 10; i++){new Thread(() => Console.Write(i)).Start();}}// i 在循环的整个生命周期内指向的是同一个内存地址// 每个线程对Console.WriteLine()的调用都会在它运行的时候进行修改。}}
- 解决方案(但是顺序还是无法保证) ```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(); } }
// 顺序仍然无法保证}
}
<a name="9f65u"></a>## 异常处理- 创建线程时在作用范围内的try/catch/finally块,在线程开始执行后就与线程无关了。```csharpusing System;using System.Threading;namespace ThreadTest{class Program{static void Main(){try{new Thread(Go).Start();}catch (Exception e){// 从不执行到这Console.WriteLine("Exception!" + e.Message);}}static void Go(){throw new NullReferenceException();}// 补救方法就是把异常处理放在Go方法里面}}-------------------------------------------处理------------------using System;using System.Threading;namespace ThreadTest{class Program{static void Main(){new Thread(Go).Start();}static void Go(){try{throw new NullReferenceException();}catch (Exception e){Console.WriteLine("Exception!" + e.Message);}}}}
- 在WPF、WinForm里,可以订阅全局异常处理事件:
- Application.DispatcherUnhandleException
- Application.ThreadException
- 触发:在通过消息循环调用的程序的任何部分发生未处理的异常(这相当于应用程序处于活动状态时,在主线程上运行的所有代码)后,将触发这些异常。
- 但是非UI线程上的未处理异常,并不会触发它。
- 而任何线程有任何未处理的异常都会触发
- AppDomain.CurrentDomain.UnhandleException
