这里我要强调一个概念,
多线程是多线程,
异步编程是异步编程
这两个是有区别的概念;
我可以说多线程天生就要异步的特点;但你不能说多线程成就等同于我们的异步编程;
根不能说异步编程就是我们的多线程。这里不要搞混淆了;
再net中的进化如下:
多线程:Thread =>ThreadPool=> Task
异步编程:BenginInvokeXXX EndInvokeXXX IAsyncResult=> async await (这里面配合着Task的使用)(基于任务的异步模式 (TAP) 时来使用异步操作)
好接下来,再来总结我们的线程(任务)的等待。
总结:
方法一:Thread.Sleep(),这个要预估,等待的时间应该大于我们的子线程执行的时间。
方法二:当然就是我们最常用的Join() 方法了,堵塞当前调用子线程成的方法,直到我们的子线程执行完毕。
方法二:主线程轮训子线程(这个是基于我们的IasyncResult 编程模式的,及时传说中的beginxxxx endxxxx这种模式)
方法三:采用通知的方法就是我们的EevntWaitHanld = new AutoRestEevnt(false),然后waitOne 和 Set 的方式来进行的,效果非常好滴呀;
方法四:我把它命名为偏方:就是利用独占锁的机制,当子线程用完锁之后,释放,让给我们的主线程,前提是要确保我们的子线程先得到锁;
方法五:这个就是基于我们的Task的wait方法;
这里我给出一些,练习的demo,仅供参考使用;
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication13 { //我们把它叫做等待子线程,或者,等待子线程一定的时间; //最原始的是使用 waitEevnt的方法;我们甚至可以用 poll的方式; //还有基于事件编程的回调方式; public class Person { } class Program { //evnet wait handle //该方法也可以用来进行线程的同步滴呀; public static object locker = new object(); public static EventWaitHandle handler = new AutoResetEvent(false); public static void Eat() { Thread.Sleep(3000); } public static void Eat_WithSet() { Thread.Sleep(3000); handler.Set(); //子线程发出做完实行的信号; } public static void Eat_WithLock() { Console.WriteLine("枷锁开始"); lock (locker) { Thread.Sleep(3000); //假设,我们这里有很多的是事情要做的呀; //效果非常好; } Console.WriteLine("枷锁释放"); } public static void Eat_Loop() { for (int i = 0; i < 10; i++) { Thread.Sleep(1000); Console.WriteLine("子"); } } //那么这个方法就不能为空了 public static void Eat_Wait() { for (int i = 0; i < 10; i++) { Task.Delay(1000).Wait(); Console.WriteLine("子"); } } public static void TestJoin() { Console.WriteLine("main start"); Thread thread = new Thread(Eat); thread.Start(); //给我等着; Console.WriteLine("主线程先做点其他事情;"); //这我们我们可以直接用线程自带的方法; thread.Join(); Console.WriteLine("好了,子线程事情做完了.."); Console.WriteLine("main end"); Console.ReadLine(); } public static void Test_Set() { Console.WriteLine("main start"); Thread thread = new Thread(Eat_WithSet); thread.Start(); //给我等着; Console.WriteLine("主线程先做点其他事情;"); handler.WaitOne(); Console.WriteLine("好了,子线程事情做完了.."); Console.WriteLine("main end"); Console.ReadLine(); } public static void Test11() { Console.WriteLine("main start"); Thread thread = new Thread(Eat_WithSet); thread.Start(); //给我等着; Console.WriteLine("主线程先做点其他事情;"); handler.WaitOne(TimeSpan.FromSeconds(3)); //注意这里,一点 waitone 和 task.wait 如果都指定了 等待的时间; //如果子线程在指定的时间内没有做完时间,那么我们就开始了主线程的方法; //这里并没有真正的取消线程; //问题又来了,如果去取消子线程呢;这个...... Console.WriteLine("好了,不堵塞,主线程了,"); Console.WriteLine("main end"); Console.ReadLine(); } //偏方 public static void Test_Lock() { Console.WriteLine("main start"); Thread thread = new Thread(Eat_WithLock); thread.Start(); //给我等着; Console.WriteLine("主线程先做点其他事情;"); //如果是单线层的话,我还是使用一点偏方; //那就是我们的lock方法滴呀; Thread.Sleep(20);//为了让子线程得到锁,我们这里估计sleep一下了 //所以尼玛的叫偏方了; lock (locker) { //当然这种方式,就是完全出去一种四等的状态; //等待另外一个线程释放锁; Console.WriteLine("这个表示我们的另外一个线程执行完毕了;"); } Console.ReadLine(); } //如果要取消原来的方法的话,还得到原来的的方法去操作,整的是麻烦的一件事情; //不过有我们的Task 就方便多;; public static void Test_Task() { //task的取消就相对简单的多了; Console.WriteLine("main start"); Task task = Task.Run(()=>Eat_Wait()); Console.WriteLine("mian do something.then wait task"); // task.Wait(); //默认情况下,它会等待task执行完毕; task.Wait(TimeSpan.FromSeconds(3));//在这里只能等待三秒,三秒只有,就不堵塞我们的主线程; //这里这的注意的事情是,等待不等于取消哦; //这一点是相对非常关键的啦; //先一节我们再来略略线程的取消啦滴呀; Console.WriteLine("task completed..."); Console.WriteLine("main end"); Console.ReadLine(); } static void Main(string[] args) { //Test(); //Test1(); //Test11(); //Test_Lock(); //Test_Task(); } } }
//这里我再来演示一个set 之后,通知多个线程的实例,或则理解成为广播是似的传递消息;
或则:多个线程在等待某一个线程的信号;
to do
线程只有不断的去判断他的isalive属性;
异步编程则可以使用的轮训的回调的方式; 如果你的主线程一直等待,那么 尼玛的就叫异步编程了;
public static void Test_IsAlive() { //Eat_Loop Console.WriteLine("main start"); Thread thread = new Thread(Eat_Loop); thread.Start(); Console.WriteLine("mian do something.then wait task"); while (thread.IsAlive) { Thread.Sleep(100); Console.WriteLine("子线程还在zuoshiser"); } Console.WriteLine("子线程把事儿做完了!"); Console.WriteLine("mian end"); } public static int CountInfo(int x) { Thread.Sleep(5000); return x+100; } public static void Test_IsComplete() { //异步编程了 Func<int, int> fn = CountInfo; IAsyncResult actionResult = fn.BeginInvoke(100, CountInfoCallback, null); //既没有回调,也没有参数这样的方法不太正常; while (!actionResult.IsCompleted) { Thread.Sleep(100); Console.WriteLine("子线程还在zuoshiser"); } //做完之后 记得endinvoke; int result= fn.EndInvoke(actionResult); //这样就可以得到我们的结果; //在这里结束,也可以在回调方法中结束 endInvoek; } static void CountInfoCallback(IAsyncResult iar) { Console.WriteLine("这里是回调...."); AsyncResult ar = (AsyncResult)iar; Func<int, int> del = (Func<int, int>)ar.AsyncDelegate; var result = del.EndInvoke(iar); //总的的来说,就是我们的采用回调和轮训的两种方式; //来实现我们的异步编程的实现; //不过好在,现在我们又了 async 和await 基于task的异步编程; //那效果,整的是杠杠的,效果是非常好滴呀; }
好了就到这里;。