在我们做项目的时候会经常用到线程,但线程也不是万能的,用线程需要注意的东西也很多,自己做了一下总结
这次总结主要说三个部分
我们先看一下小例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadMethod { class Program { static void Main(string[] args) { ThreadStart _ts = new ThreadStart(MyThread); Thread _thread1 = new Thread(_ts); _thread1.Start(); Console.WriteLine("other Metod"); Console.ReadLine(); } public static void MyThread() { for (int i = 0; i < 10; i++) { Console.WriteLine(i + " by Thread " + Thread.CurrentThread.ManagedThreadId); } } } }
在方法里我们定义了一个 ThreadStart _ts = new ThreadStart(MyThread);
打开msdn 查看发现这是一个委托 ,表示在 Thread 上执行的方法。
[ComVisible(true)] public delegate void ThreadStart();
那就是说也可以这么写
Thread _thread2 = new Thread(delegate() { for (int i = 0; i < 5; i++) { Console.WriteLine(i + " by Thread " + Thread.CurrentThread.ManagedThreadId); } }); //或者 Thread _thread3 = new Thread(()=> { for (int i = 0; i < 5; i++) { Console.WriteLine(i + " by Thread " + Thread.CurrentThread.ManagedThreadId); } }); _thread2.Start(); _thread3.Start();
Thread类有一个带参数的委托类型的重载形式
[ComVisibleAttribute(false)] public delegate void ParameterizedThreadStart ( Object obj )
可以传递一个object参数,因为是个委托我们也可以和上面的那么写
class Program { static void Main(string[] args) { Thread _thread = new Thread(new ParameterizedThreadStart(MyParametFun)); _thread.Start("aaa"); Thread _thread2 = new Thread(x => { Console.WriteLine(x); }); _thread2.Start("bbb"); Console.WriteLine("other Metod"); Console.ReadLine(); } public static void MyParametFun(object f_str) { Console.WriteLine(f_str); } }
有时个我们有好几个参数只传一个参数据就不能满足了
我们可以直接用委托要多个参数
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadMethod { class Program { static void Main(string[] args) { int _x = 1; string _str = "abc"; string _str2 = "aaaaa"; Thread _thread=new Thread(()=>{ Console.WriteLine(_x); Console.WriteLine(_str); Console.WriteLine(_str2); }); _thread.Start(); Console.WriteLine("other Metod"); Console.ReadLine(); } } }
也可以自己写一个中间类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadMethod { class Program { static void Main(string[] args) { MyMode _myMode = new MyMode(1, "aa", "bb"); Thread _thread = new Thread(_myMode.ConsoFun); _thread.Start(); Console.WriteLine("other Metod"); Console.ReadLine(); } } public class MyMode { int _x ; string _str ; string _str2 ; public MyMode() { } public MyMode(int f_x,string f_str1,string f_str2) { _x = f_x; _str = f_str1; _str2 = f_str2; } public void ConsoFun() { Console.WriteLine(_x); Console.WriteLine(_str); Console.WriteLine(_str2); } } }
三种方法lock 和Monitor 还有MethodImpl都会让线程同步下面我们一个一个的来说
多个线程访问同一个方法时有可能会出现一个线程修改了一个参数别一个线程进入也修改了这个参数就会发生
错误
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadMethod { class Program { static int sum = 200; static void Main(string[] args) { Thread _t1 = new Thread(ConFun); Thread _t2 = new Thread(ConFun); _t1.Start(); _t2.Start(); Console.WriteLine("other Metod"); Console.ReadLine(); } public static void ConFun() { int i = 0; while (i <= 10) { sum -= i; Thread.Sleep(10); ++i; } Console.WriteLine(sum); } } }
结果是
根据机器的配制不同可能结果也不同
在这个方法里我们是想让第一个线程减10结果应该 是145
第二个线程进去后在145基础上再减结果应该是90
现在说三种方法lock 和Monitor 还有MethodImpl 都会让线程同步,只有一个线程执行完后另一个线程才能访问
我们一个一个来说吧
先看一下lock
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Runtime.CompilerServices; namespace ThreadMethod { class Program { static object obj = new object(); static int sum = 200; static void Main(string[] args) { Thread _t1 = new Thread(ConFun); Thread _t2 = new Thread(ConFun); _t1.Start(); _t2.Start(); Console.WriteLine("other Metod"); Console.ReadLine(); } public static void ConFun() { lock (obj) { int i = 0; while (i <= 10) { sum -= i; Thread.Sleep(10); ++i; } } Console.WriteLine(sum); } } }
这样结果就对了吧
还有其它的两种形式
用MethodImpl 要加上
using System.Runtime.CompilerServices;
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Runtime.CompilerServices; namespace ThreadMethod { class Program { static object obj = new object(); static int sum = 200; static void Main(string[] args) { Thread _t1 = new Thread(ConFun); Thread _t2 = new Thread(ConFun); _t1.Start(); _t2.Start(); Console.WriteLine("other Metod"); Console.ReadLine(); } [MethodImpl(MethodImplOptions.Synchronized)] public static void ConFun() { int i = 0; while (i <= 10) { sum -= i; Thread.Sleep(10); ++i; } Console.WriteLine(sum); }
Monitor
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadMethod { class Program { static object obj = new object(); static int sum = 200; static void Main(string[] args) { Thread _t1 = new Thread(ConFun); Thread _t2 = new Thread(ConFun); _t1.Start(); _t2.Start(); Console.WriteLine("other Metod"); Console.ReadLine(); } public static void ConFun() { Monitor.Enter(obj); int i = 0; while (i <= 10) { sum -= i; Thread.Sleep(10); ++i; } Monitor.Exit(obj); Console.WriteLine(sum); } } }
结果都是正确的