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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

[C#基础]c#中的BeginInvoke和EndEndInvoke

發布時間:2023/12/15 C# 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [C#基础]c#中的BeginInvoke和EndEndInvoke 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

摘要

異步這東西,真正用起來的時候,發現事情還是挺多的,最近在項目中用到了異步的知識,發現對它還是不了解,處理起來,走了不少彎路。覺得還是補一補還是很有必要的。

MSDN原文地址:https://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.110).aspx

正文

.Net framework可以讓你異步調用任何方法。為達這樣的目的,你可以定義一個與你要調用的方法的簽名相同的委托。公共語言運行時將自動為該委托定義與簽名相同的BeginInvok和EndInvoke方法。

異步委托調用BeginInvok和EndInvoke方法,但在.NET Compact Framework中并不支持。

BeginInvoke方法觸發你的異步方法,它和你想要執行的異步方法有相同的參數。另外還有兩個可選參數,第一個是AsyncCallback委托是異步完成的回調方法。第二個是用戶自定義對象,該對象將傳遞到回調方法中。BeginInvoke立即返回并且不等待完成異步的調用(繼續執行該下面的代碼,不需要等待)。BeginInvoke返回IAsyncResult接口,可用于檢測異步調用的過程。

通過EndInvoke方法檢測異步調用的結果。如果異步調用尚未完成,EndInvoke將阻塞調用線程,直到它完成。EndInvoke參數包括out和ref參數。

下面代碼演示使用BeginInvoke和EndInvoke進行異步調用的四種常見方式。在調用BeginInvoke可以做以下工作:

  • 做一些其他操作,然后調用EndInvoke方法阻塞線程直到該方法完成。
  • 使用IAsyncResult.AsyncWaitHandle屬性,使用它的WaitOne方法阻塞線程直到收到WaitHandle信號,然后調用EndInvoke。
  • 檢查BeginInvoke返回值IAsyncResult的狀態來決定方法是否完成,然后調用EndInvoke方法。
  • 通過在BeginInvoke方法中傳遞該委托,在回調方法中調用該委托的EenInvoke方法。
  • 注意

    無論你怎么使用,都必須調用EndInvoke方法結束你的異步調用。

    下面通過模擬一個耗時的操作,實現上面說的那四種情況。

    情況一:通過EndInovke阻塞線程,直到異步調用結束。

    using System; using System.Diagnostics; using System.Threading;namespace BeginInvokeDemo {/// <summary>/// 委托必須和要調用的異步方法有相同的簽名/// </summary>/// <param name="callDuration">sleep時間</param>/// <param name="threadId">當前線程id</param>/// <returns></returns>public delegate string AsyncMethodCaller(int callDuration, out int threadId);class Program{/// <summary>/// 主函數/// </summary>/// <param name="args"></param>static void Main(string[] args){AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync);int threadid = 0;//開啟異步操作IAsyncResult result = caller.BeginInvoke(3000, out threadid, null, null);for (int i = 0; i < 10; i++){Console.WriteLine("其它業務" + i.ToString());}//調用EndInvoke,等待異步執行完成Console.WriteLine("等待異步方法TestMethodAsync執行完成");string res = caller.EndInvoke(out threadid, result);Console.WriteLine("Completed!");Console.WriteLine(res);Console.Read();}/// <summary>/// 與委托對應的方法/// </summary>/// <param name="callDuration"></param>/// <param name="threadId"></param>/// <returns></returns>static string TestMethodAsync(int callDuration, out int threadId){Stopwatch sw = new Stopwatch();sw.Start();Console.WriteLine("異步TestMethodAsync開始");for (int i = 0; i < 5; i++){ // 模擬耗時操作 Thread.Sleep(callDuration);Console.WriteLine("TestMethodAsync:" + i.ToString());}sw.Stop();threadId = Thread.CurrentThread.ManagedThreadId;return string.Format("耗時{0}ms.", sw.ElapsedMilliseconds.ToString());}} } View Code

    結果

    由上圖,可以看出,在BeginInvoke開啟異步執行方法,會先執行其他的業務。通過EndInvoke方法,阻塞直到異步執行完畢,才會執行EndInvoke之后的代碼。

    情況二:通過WaitHandle屬性阻塞線程。

    你可以獲得BeginInvoke的返回值的WaitHandle,并使用它的AsyncWaitHanlde屬性。WaitHandle信號異步完成時,你可以通過調用WaitOne方法等待。

    如果你使用WaitHandle,你可以在之前或者異步調用完成后進行其他的操作。但之后必須使用EndInvoke檢查結果。

    注意

    當你調用EndInvoke方法時,等待句柄并不會自動關閉。如果你釋放等待處理的所有引用,當垃圾回收等待句柄是,系統資源將被釋放。一旦你完成使用等待句柄,通過WaitHandle的close方法,一次性顯示關閉,這時的垃圾回收效率更高。

    using System; using System.Diagnostics; using System.Threading;namespace BeginInvokeDemo {/// <summary>/// 委托必須和要調用的異步方法有相同的簽名/// </summary>/// <param name="callDuration">sleep時間</param>/// <param name="threadId">當前線程id</param>/// <returns></returns>public delegate string AsyncMethodCaller(int callDuration, out int threadId);class Program{/// <summary>/// 主函數/// </summary>/// <param name="args"></param>static void Main(string[] args){AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync);int threadid = 0;//開啟異步操作IAsyncResult result = caller.BeginInvoke(3000, out threadid, null, null);for (int i = 0; i < 10; i++){Console.WriteLine("其它業務" + i.ToString());}//調用EndInvoke,等待異步執行完成Console.WriteLine("等待異步方法TestMethodAsync執行完成");//等待異步執行完畢信號 result.AsyncWaitHandle.WaitOne();Console.WriteLine("收到WaitHandle信號");//通過EndInvoke檢查結果string res = caller.EndInvoke(out threadid, result);//顯示關閉句柄 result.AsyncWaitHandle.Close();Console.WriteLine("關閉了WaitHandle句柄");Console.WriteLine("Completed!");Console.WriteLine(res);Console.Read();}/// <summary>/// 與委托對應的方法/// </summary>/// <param name="callDuration"></param>/// <param name="threadId"></param>/// <returns></returns>static string TestMethodAsync(int callDuration, out int threadId){Stopwatch sw = new Stopwatch();sw.Start();Console.WriteLine("異步TestMethodAsync開始");for (int i = 0; i < 5; i++){ // 模擬耗時操作 Thread.Sleep(callDuration);Console.WriteLine("TestMethodAsync:" + i.ToString());}sw.Stop();threadId = Thread.CurrentThread.ManagedThreadId;return string.Format("耗時{0}ms.", sw.ElapsedMilliseconds.ToString());}} }

    輸出

    情況三:檢查BeginInvoke返回結果的狀態。

    可以通過BeginInvoke的返回結果的IsCompleted屬性檢查異步是否完成。你可以在異步沒有完成的時候做其他的操作。

    using System; using System.Diagnostics; using System.Threading;namespace BeginInvokeDemo {/// <summary>/// 委托必須和要調用的異步方法有相同的簽名/// </summary>/// <param name="callDuration">sleep時間</param>/// <param name="threadId">當前線程id</param>/// <returns></returns>public delegate string AsyncMethodCaller(int callDuration, out int threadId);class Program{/// <summary>/// 主函數/// </summary>/// <param name="args"></param>static void Main(string[] args){AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync);int threadid = 0;//開啟異步操作IAsyncResult result = caller.BeginInvoke(1000, out threadid, null, null);for (int i = 0; i < 10; i++){Console.WriteLine("其它業務" + i.ToString());}//調用EndInvoke,等待異步執行完成Console.WriteLine("等待異步方法TestMethodAsync執行完成");//等待異步執行完畢信號//result.AsyncWaitHandle.WaitOne();//Console.WriteLine("收到WaitHandle信號");//通過循環不停的檢查異步運行狀態while (result.IsCompleted==false){Thread.Sleep(100);Console.WriteLine("異步方法,running........");}//異步結束,拿到運行結果string res = caller.EndInvoke(out threadid, result);//顯示關閉句柄 result.AsyncWaitHandle.Close();Console.WriteLine("關閉了WaitHandle句柄");Console.WriteLine("Completed!");Console.WriteLine(res);Console.Read();}/// <summary>/// 與委托對應的方法/// </summary>/// <param name="callDuration"></param>/// <param name="threadId"></param>/// <returns></returns>static string TestMethodAsync(int callDuration, out int threadId){Stopwatch sw = new Stopwatch();sw.Start();Console.WriteLine("異步TestMethodAsync開始");for (int i = 0; i < 5; i++){ // 模擬耗時操作 Thread.Sleep(callDuration);Console.WriteLine("TestMethodAsync:" + i.ToString());}sw.Stop();threadId = Thread.CurrentThread.ManagedThreadId;return string.Format("耗時{0}ms.", sw.ElapsedMilliseconds.ToString());}} } View Code

    輸出

    其它業務0 其它業務1 其它業務2 其它業務3 其它業務4 其它業務5 其它業務6 其它業務7 其它業務8 其它業務9 等待異步方法TestMethodAsync執行完成 異步TestMethodAsync開始 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ TestMethodAsync:0 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ TestMethodAsync:1 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ TestMethodAsync:2 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ TestMethodAsync:3 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ 異步方法,running........ TestMethodAsync:4 異步方法,running........ 關閉了WaitHandle句柄 Completed! 耗時5031ms.

    情況四:通過在回調方法中。

    如果需要在異步完成后需要做一些其他的操作,你可以在異步完成時執行一個回調方法。在該回調方法中做處理。

    首先需要定義一個回調方法。

    using System; using System.Diagnostics; using System.Threading;namespace BeginInvokeDemo {/// <summary>/// 委托必須和要調用的異步方法有相同的簽名/// </summary>/// <param name="callDuration">sleep時間</param>/// <param name="threadId">當前線程id</param>/// <returns></returns>public delegate string AsyncMethodCaller(int callDuration, out int threadId);class Program{/// <summary>/// 主函數/// </summary>/// <param name="args"></param>static void Main(string[] args){AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync);int threadid = 0;//開啟異步操作IAsyncResult result = caller.BeginInvoke(1000, out threadid, callBackMethod, caller);for (int i = 0; i < 10; i++){Console.WriteLine("其它業務" + i.ToString());}//調用EndInvoke,等待異步執行完成Console.WriteLine("等待異步方法TestMethodAsync執行完成");//等待異步執行完畢信號//result.AsyncWaitHandle.WaitOne();//Console.WriteLine("收到WaitHandle信號");//通過循環不停的檢查異步運行狀態//while (result.IsCompleted==false)//{// Thread.Sleep(100);// Console.WriteLine("異步方法,running........");//}//異步結束,拿到運行結果//string res = caller.EndInvoke(out threadid, result);////顯示關閉句柄//result.AsyncWaitHandle.Close();Console.WriteLine("關閉了WaitHandle句柄");//Console.WriteLine(res); Console.Read();}/// <summary>/// 異步方法回調方法,異步執行完畢,會回調該方法/// </summary>/// <param name="ar"></param>private static void callBackMethod(IAsyncResult ar){AsyncMethodCaller caller = ar.AsyncState as AsyncMethodCaller; string result = caller.EndInvoke(out int threadid, ar);Console.WriteLine("Completed!");Console.WriteLine(result);}/// <summary>/// 與委托對應的方法/// </summary>/// <param name="callDuration"></param>/// <param name="threadId"></param>/// <returns></returns>static string TestMethodAsync(int callDuration, out int threadId){Stopwatch sw = new Stopwatch();sw.Start();Console.WriteLine("異步TestMethodAsync開始");for (int i = 0; i < 5; i++){ // 模擬耗時操作 Thread.Sleep(callDuration);Console.WriteLine("TestMethodAsync:" + i.ToString());}sw.Stop();threadId = Thread.CurrentThread.ManagedThreadId;return string.Format("耗時{0}ms.", sw.ElapsedMilliseconds.ToString());}} }

    總結

    在項目中遇到的有參數又返回值的情況,如何在回調方法中拿到委托和傳遞的參數,當時卡這里了,后來查看情況四的情況,才得以解決。這里也再學習一下。

    轉載于:https://www.cnblogs.com/wolf-sun/p/5675791.html

    總結

    以上是生活随笔為你收集整理的[C#基础]c#中的BeginInvoke和EndEndInvoke的全部內容,希望文章能夠幫你解決所遇到的問題。

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