线程和异步
线程与进程
进程和线程放在一起谈比较好理解。
进程可理解为一个应用程序。一个进程中只有一个任务,就是单线程,有多个任务就是多线程。
下面附上一个线程的小例子。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class Printer { public void PrintNumbers() { Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name); Console.Write("Your numbers: "); for (int i = 0; i < 5; i++) { Console.Write("{0}", i); Thread.Sleep(2000);//间隔2秒 } } } class Program { static void Main(string[] args) { Printer print = new Printer(); ThreadStart thread = print.PrintNumbers;//ThreadStart委托 Thread t = new Thread(thread); t.IsBackground = true;//默认为前台线程,不会随Main()方法的结束而结束。可以设置thread.IsBackground为True,则转为后台线程,即可随Main()方法的结束而结束。 t.Start(); //Thread t = new Thread(new ThreadStart(print.PrintNumbers)); //t.Name = "Thread"; //t.Priority = ThreadPriority.Highest; //t.Start(); //第一种写的清楚点,第二种写的简易。 MessageBox.Show("************test************"); } }
开启一个线程运行Print操作 同时也显示了提示信息。如果不用线程则将等Print结束后才可以显示提示信息。
前后台线程在进行解释:前台线程可以阻止应用程序的终结,要一直等到所有前台线程结束方可终结,而后台线程当应用程序终结时,所有的后台线程也自动终止。
创建10个线程
Thread [] threads= new Thread[10]; for(int i=0;i<10;i++) { threads[i]=new Thread(new ThreadStart(XX方法名)); }
多线程共同使用某个共享资源的时候,会造成冲突。
举个生活例子以及解救方法
生活中我们会遇到这样的情况:去商场买衣服时,如果想要试一试是否合身,一般可以利用商场提供的试衣间,但一个试衣间一个时间段内只能有一个人在试衣。如果有多个人都要使用同一个试衣间(共享资源),而试衣间的门又没有加锁,则会存在共享资源的冲突问题。
实际生活中,这个问题是这样解决的:
现在假设有A、B、C同时要使用试衣间,A进去后,将门锁上,B看到门已上锁,则知道有人在试衣,会进行等待,A使用完试衣间后,打开锁(解除对共享资源的锁定),则B知道此时试衣间可以使用,则B使用试衣间。C同样。
简单的一把锁,解决了试衣间的使用冲突问题。
在代码中使用lock关键字来进行锁定。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class Printer { private object threadLock = new object(); public void PrintNumbers() { lock (threadLock)//所有的代码都必须在锁定范围中 { Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name); Console.Write("Your numbers: "); for (int i = 0; i < 5; i++) { Console.Write("{0}", i); Thread.Sleep(2000); } } } }
线程池
同样使用Print操作来展示线程池的例子。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class Printer { private object threadLock = new object(); public void PrintNumbers() { lock (threadLock) { Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name); Console.Write("Your numbers: "); for (int i = 0; i < 5; i++) { Console.Write("{0}", i); Thread.Sleep(2000); } } } } class Program { public static void PrintTheNumbers(object state) { Printer task = (Printer)state;//传入对象转化成自定义类并调用方法传入委托WaitCallback task.PrintNumbers(); } static void Main(string[] args) { Printer p = new Printer(); WaitCallback workItem = new WaitCallback(PrintTheNumbers);//WaitCallBack是委托 通过New也可以启用多个线程 ThreadPool.QueueUserWorkItem(workItem, p);//启动线程池 Console.ReadLine(); } }
线程池好处:
1. 线程池减少了线程的创建,开始和停止的次数,提高了效率;
2.使用线程池,可以将注意力放到业务逻辑上而不是多线程架构上。
与线程作用异曲同工之妙的是异步调用。
异步与多线程解决的是提高数据处理能力,并行运行程序。
异步不需要等待返回值就继续执行,同步需要等待返回值。
同样也给一个例子。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public delegate void BinaryOp(); public class Printer { private object threadLock = new object(); public void PrintNumbers() { lock (threadLock) { Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name); Console.Write("Your numbers: "); for (int i = 0; i < 5; i++) { Console.Write("{0}", i); Thread.Sleep(2000); } } } } class Program { static void Main(string[] args) { Printer a = new Printer(); BinaryOp b = a.PrintNumbers;//该方法无参 故下面两个NULL IAsyncResult result = b.BeginInvoke(null, null);//开启异步调用 MessageBox.Show("************test************"); Console.ReadLine(); } }