標籤:name syn 問題 pre auto obj result public 混淆
這裡我要強調一個概念,
多線程是多線程,
非同步編程是非同步編程
這兩個是有區別的概念;
我可以說多線程天生就要非同步特點;但你不能說多線程成就等同於我們的非同步編程;
根不能說非同步編程就是我們的多線程。這裡不要搞混淆了;
再net中的進化如下:
多線程:Thread =>ThreadPool=> Task
非同步編程:BenginInvokeXXX EndInvokeXXX IAsyncResult=> async await (這裡面配合著Task的使用)。
好接下來,再來總結我們的線程(任務)的等待。
總結:
方法一: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 之後,通知多個線程的執行個體,或則理解成為廣播是似的傳遞訊息;
或則:多個線程在等待某一個線程的訊號;
c# 線程的等待(堵塞)