分享一個非同步執行緒,輪詢的demo
阿新 • • 發佈:2019-02-13
//建立一個控制檯應用程式如下:
using System; using System.Threading; namespace ConsoleApplication1 { public delegate string AsyncDelegate(int callDuration, out int threadId); class Program { static void Main(string[] args) { //Fun1(); //Fun2(); //Fun3(); Fun4(); Console.ReadLine(); } private static int threadId; //阻塞等待 使用 EndInvoke 等待非同步呼叫 static void Fun1() { //建立示例類的例項。 AsyncDemo ad = new AsyncDemo(); // 建立委託 AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod); // 委託在這裡開始非同步呼叫。 IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, null, null); //人為的執行緒阻塞。 Thread.Sleep(0); //Thread.CurrentThread.Name = "主執行緒"; Console.WriteLine("主執行緒 {0}開始工作",Thread.CurrentThread.ManagedThreadId); // 委託開始EndInvoke呼叫,這個過程會使主執行緒等待非同步呼叫完成並返回結果。 string ret = dlgt.EndInvoke(out threadId, ar); Console.WriteLine("使用 EndInvoke 等待非同步呼叫!!!"); Console.WriteLine("非同步執行緒 {0},返回值 \"{1}\".", threadId, ret); Console.WriteLine("主執行緒{0}結束工作", Thread.CurrentThread.ManagedThreadId); } //阻塞等待 使用 WaitHandle 等待非同步呼叫 static void Fun2() { AsyncDemo ad = new AsyncDemo(); AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod); IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, null, null); Thread.Sleep(0); Console.WriteLine("主執行緒 {0}開始工作", Thread.CurrentThread.ManagedThreadId); //主執行緒在這裡等待,直到非同步執行緒執行完。 ar.AsyncWaitHandle.WaitOne(); // 和前一方案的區別在於,你可以在非同步呼叫完成後,獲取非同步呼叫返回值之前 //在這裡做點任何你想作的事。 //呼叫EndInvoke獲取非同步呼叫的返回結果. string ret = dlgt.EndInvoke(out threadId, ar); Console.WriteLine("使用 WaitHandle 等待非同步呼叫!!!"); Console.WriteLine("非同步執行緒 {0},返回值 \"{1}\".", threadId, ret); Console.WriteLine("主執行緒{0}結束工作", Thread.CurrentThread.ManagedThreadId); } //輪詢狀態 輪詢非同步呼叫完成 static void Fun3() { AsyncDemo ad = new AsyncDemo(); AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod); IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, null, null); Console.WriteLine("使用輪詢非同步呼叫!!!"); Console.WriteLine("主執行緒 {0}開始工作", Thread.CurrentThread.ManagedThreadId); //這裡每隔10毫秒就檢測(輪詢)一下非同步執行的狀態, //直到非同步呼叫完成,IsCompleted的值變為ture為止。 int count = 0; DateTime a = DateTime.Now; while (ar.IsCompleted == false) { Thread.Sleep(10); count++; } string dt = (DateTime.Now - a).ToString(); Console.WriteLine(count); Console.WriteLine("程式耗時"+dt); //還記得微軟的那個善意的提醒嗎?雖然IsCompleted為true了, //我們還是呼叫一下EndInvoke,來獲取返回值。 string ret = dlgt.EndInvoke(out threadId, ar); Console.WriteLine("非同步執行緒 {0},返回值 \"{1}\".", threadId, ret); Console.WriteLine("主執行緒{0}結束工作", Thread.CurrentThread.ManagedThreadId); } //通知機制 非同步呼叫完成時執行回撥方法 static void Fun4() { AsyncDemo ad = new AsyncDemo(); AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod); //注意第三個引數,這就是我們要用到的回撥方法。 //第四個引數更為有趣,它可以是任何Object物件,這裡它就是 //執行非同步呼叫的委託本身,把委託本身傳遞進去的原因在下面可以看到。 Console.WriteLine("非同步呼叫完成時執行回撥!!!"); Console.WriteLine("主執行緒 {0}開始工作", Thread.CurrentThread.ManagedThreadId); IAsyncResult ar = dlgt.BeginInvoke(5000,out threadId, new AsyncCallback(CallbackMethod), dlgt); Console.WriteLine("主執行緒 {0}結束工作", Thread.CurrentThread.ManagedThreadId); Console.ReadLine(); } //回撥函式必須嚴格的遵照AsyncCallback委託的簽名。 static void CallbackMethod(IAsyncResult ar) { //在這裡,上面那個dlgt作為引數的作用得到了體現,原來它就是為了完成對EndInvoke的呼叫啊。 AsyncDelegate dlgt = (AsyncDelegate)ar.AsyncState; //通過對EndInvoke的呼叫獲取返回值。 string ret = dlgt.EndInvoke(out threadId, ar); Console.WriteLine("非同步執行緒 {0},返回值 \"{1}\".", threadId, ret); } } //使用非同步程式設計模型 public class AsyncDemo { public string TestMethod(int callDuration, out int threadId) { Console.WriteLine("非同步方法開始工作"); Thread.Sleep(callDuration); //Thread.CurrentThread.Name = "非同步執行緒"; threadId = Thread.CurrentThread.ManagedThreadId; return "非同步方法執行時間 " + callDuration.ToString(); } } }
上面的註釋都很詳細相信大家很容易看得懂。
為博主轉載,忘記此demo的出處了,如若侵權,即可刪除。