日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。

發布時間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一. 再談委托

1. 委托是一個關鍵字為delegate的自定義類型,通過委托可以把方法以參數的形式傳遞給另外一個方法,實現插件式的開發模式;

? ? 同時調用委托的時候,委托所包含的所有方法都會被實現。

2. 委托的發展歷史:new實例化傳遞方法→直接等于方法名→delegate匿名方法→省略delegate→省略括號中的參數→當只有一個參數省略小括號

         ?→當方法體只有一行,省略大括號

 (詳見:http://www.cnblogs.com/yaopengfei/p/6959141.html)

3:常用的Action委托和Func委托

  A. Action<>委托,無返回值,至少有一個參數的委托

  B. Func<>委托,有返回值,可以無參數的委托(當然也可以有參數)

  C. Action委托,無參數無返回值的委托?

二. 委托的調用

委托的調用分為兩種:

  A. 同步調用:Invoke方法,方法參數為函數的參數。

  B. 異步調用:BeginInvoke方法。

其中無論是哪類調用,都有兩類寫法:

  ①:利用Action<>(或Func<>)內置委托,調用的時候賦值。

  ②:利用Action委托,直接賦值,然后調用。

1 /// <summary>2 /// 執行動作:耗時而已3 /// </summary>4 private void TestThread2(string threadName1, string threadName2)5 {6 Console.WriteLine("線程開始:線程名為:{2}和{3},當前線程的id為:{0},當前時間為:{1},", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2);7 long sum = 0;8 for (int i = 1; i < 999999999; i++)9 { 10 sum += i; 11 } 12 Console.WriteLine("線程結束:線程名為:{2}和{3},當前線程的id為::{0},當前時間為:{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), threadName1, threadName2); 13 }

?

?

?

?

?

?

?

三.?深入剖析BeginInvoke方法

?  首先需要明確,該方法參數個數不定, 最后兩個參數含義固定,如果不使用的話,需要賦值null;該方法最少兩個參數,即方法無參數,這種情況下BeginInvoke中只有兩個參數。此外,賦值的方法有幾個參數,BeginInvoke中從左開始,新增幾個參數。

  ①. 倒數第二個參數:是有一個參數值無返回值的委托,它代表的含義為,該線程執行完畢后的回調。

  ②. 倒數第一個參數:向倒數第二個參數(即回調)中傳值,需要用AsyncState來接受。

  ③. 其它參數:即為賦值方法的參數。

注:BeginInvoke的返回值等價于異步回調中的t。

1 private void button13_Click(object sender, EventArgs e)2 {3 Stopwatch watch = new Stopwatch();4 watch.Start();5 Console.WriteLine("----------------- button1_Click 開始 主線程id為:{0} --------------------------", Thread.CurrentThread.ManagedThreadId);6 7 Action<string> myFunc = this.TestThread;8 IAsyncResult asyncResult = null;9 //參數說明:前面幾個參數都是方法的參數值,倒數第二個為異步調用的回調函數,倒數第一個為傳給回調函數的參數 10 for (int i = 0; i < 1; i++) 11 { 12 string name = string.Format("button1_Click{0}", i); 13 asyncResult = myFunc.BeginInvoke(name, t => 14 { 15 Console.WriteLine("我是線程{0}的回調", Thread.CurrentThread.ManagedThreadId); 16 //用 t.AsyncState 來獲取回調傳進來的參數 17 Console.WriteLine("傳進來的參數為:{0}", t.AsyncState); 18 19 //測試一下異步返回值的結果 20 Console.WriteLine("異步返回值的結果:{0}", t.Equals(asyncResult)); 21 }, "maru"); 22 } 23 24 watch.Stop(); 25 Console.WriteLine("----------------- button1_Click 結束 主線程id為:{0} 總耗時:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds); 26 27 }

結果:

?

四.?線程等待的三種方式

1. asyncResult.IsCompleted屬性,該方式會存在時間上的誤差。

2. WaitOne方法,可以控制一直等待or超時不再等待。

3. EndInvoke方法,官方推薦的線程等待的方式。

以上三種方式的局限性:批量線程等待的時候,不靈活,需要for循環了。

1 private void button14_Click(object sender, EventArgs e)2 {3 Stopwatch watch = new Stopwatch();4 watch.Start();5 Console.WriteLine("----------------- button1_Click 開始 主線程id為:{0} --------------------------", Thread.CurrentThread.ManagedThreadId);6 7 IAsyncResult asyncResult = null;8 Action<string> myFunc = this.TestThread;9 string name = string.Format("button1_Click{0}", 111); 10 asyncResult = myFunc.BeginInvoke(name, t => 11 { 12 Console.WriteLine("我是線程{0}的回調", Thread.CurrentThread.ManagedThreadId); 13 //用 t.AsyncState 來獲取回調傳進來的參數 14 Console.WriteLine("傳進來的參數為:{0}", t.AsyncState); 15 }, "maru"); 16 17 //等待的方式1:會有時間上的誤差 18 //while (!asyncResult.IsCompleted) 19 //{ 20 // Console.WriteLine("正在等待中"); 21 //} 22 23 // 等待的方式二: 24 //asyncResult.AsyncWaitHandle.WaitOne();//一直等待 25 //asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待 26 //asyncResult.AsyncWaitHandle.WaitOne(1000);//等待1000毫秒,超時就不等待了 27 28 //等待的方式三: 29 myFunc.EndInvoke(asyncResult); 30 31 watch.Stop(); 32 Console.WriteLine("----------------- button1_Click 結束 主線程id為:{0} 總耗時:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds); 33 34 }

下面是多個線程等待的情況:

1 private void button15_Click(object sender, EventArgs e)2 {3 Stopwatch watch = new Stopwatch();4 watch.Start();5 Console.WriteLine("----------------- button1_Click 開始 主線程id為:{0} --------------------------", Thread.CurrentThread.ManagedThreadId);6 7 List<IAsyncResult> list = new List<IAsyncResult>();8 9 for (int i = 0; i < 5; i++) 10 { 11 string name = string.Format("button1_Click{0}", i); 12 Action myFunc = () => 13 { 14 TestThread2(name, name); 15 }; 16 var asyncResult = myFunc.BeginInvoke(null, null); 17 list.Add(asyncResult); 18 } 19 20 //下面是線程等待 21 foreach (var item in list) 22 { 23 item.AsyncWaitHandle.WaitOne(-1); 24 } 25 26 watch.Stop(); 27 Console.WriteLine("----------------- button1_Click 結束 主線程id為:{0} 總耗時:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds); 28 }

結果:

?

總結

以上是生活随笔為你收集整理的第一节:复习委托,并且通过委托的异步调用开启一个新线程和异步回调、异步等待。的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。