網站首頁 編程語言 正文
c# Invoke與BeginInvoke
最近在學習線程時,發現當我創建的線程需要訪問UI界面的時,會發生異常,原因是我在跨線程調用主線程的控件,因此windows GUI編程有一個規則,就是只能通過創建控件的線程來操作控件的數據,否則就可能產生不可預料的結果。
有時候,我們不得不跨線程調用主界面的控件來進行操作,所以為了方便的解決問題,.net為我們提供了Invoke 與beginInvoke
Invoke 與begininvoke區別在于,invoke會阻塞當前線程,直到invoke調用結束,才會繼續執行下去,而begininvoke 則可以異步進行調用,也就是該方法封送完畢后馬上返回,不會等待委托方法的執行結束,調用者線程將不會被阻塞。但是調用者也可以使用EndInvoke方法或者其它類似WaitHandle機制等待異步操作的完成。
先講下Invoke
? ? ? ? // 定義委托函數 ,委托函數與被委托函數必須要有相同返回值和參數列表
? ? ? ? public delegate void myDelegate(string str); ?
? ? ? ? public void _invoke_myDelegate(String str)
? ? ? ? {
? ? ? ? ? ? // invokeRequired 獲取一個bool值 判斷調用控件是否必須要調用invoke方法
? ? ? ? ? ? // 如果調用對象在其他線程,則返回true,否則返回false
? ? ? ? ? ? if (this.InvokeRequired)
? ? ? ? ? ? {
? ? ? ? ? ? ? ?/* Action<string> action = new Action<string>(_invoke_myDelegate);*/
? ? ? ? ? ? ? ?// 確定調用對象在其他線程 則調用invoke函數 它會返回到擁有這個控件的線程上
? ? ? ? ? ? ? ?// ?利用委托函數,再次調用被委托函數,str為委托函數的參數列表
? ? ? ? ? ? ? ?this.Invoke(new myDelegate(_invoke_myDelegate), str);
? ? ? ? ? ? }
? ? ? ? ? ? // 當委托函數執行時, 此時已經回到控件線程,可以直接調用控件label
? ? ? ? ? ? label1.Text = str;
? ? ? ? }
這里Invoke 必須等委托函數調用完成之后,才會執行后面操作,那么當我們的委托函數執行的是一個非常耗時的操作
這樣線程就會被阻塞,造成用戶界面卡頓的情況,所以,為了解決invoke同步的問題,還有一種就是beginInvoke
BeginInvoke
BeginInvoke方法觸發你的異步方法,它和你想要執行的異步方法有相同的參數。
另外還有兩個可選參數
- 1.第一個是AsyncCallback委托是異步完成的回調方法。
- 2.第二個是用戶自定義對象,該對象將傳遞到回調方法中。
BeginInvoke立即返回并且不等待完成異步的調用(繼續執行該下面的代碼,不需要等待)。
BeginInvoke返回IAsyncResult接口,可用于檢測異步調用的過程。
通過EndInvoke方法檢測異步調用的結果。如果異步調用尚未完成,EndInvoke將阻塞調用線程,直到它完成。EndInvoke參數包括out和ref參數。
不管怎么么樣,調用了beginInvoke ,就必須調用endInvoke 結束異步,
那我們怎么才能知道什么時候異步結束呢?
常見四種方法:
- 1.做一些其他操作,然后調用EndInvoke方法阻塞線程直到該方法完成。
- 2.使用IAsyncResult.AsyncWaitHandle屬性,使用它的WaitOne方法阻塞線程直到收到WaitHandle信號,然后調用EndInvoke。
- 3.檢查BeginInvoke返回值IAsyncResult的狀態來決定方法是否完成,然后調用EndInvoke方法。
- 4.通過在BeginInvoke方法中傳遞該委托,在回調方法中調用該委托的EndInvoke方法。? ? ? ?
? ?AsyncMethodCaller caller = new AsyncMethodCaller(TestMethodAsync); // caller 為委托函數
? ? ? ? ? ? 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句柄");
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://blog.csdn.net/qq_41145567/article/details/80781475
相關推薦
- 2022-09-05 C語言之關于二維數組在函數中的調用問題_C 語言
- 2022-09-20 Redis超詳細分析分布式鎖_Redis
- 2022-03-31 C#實現學生檔案查詢_C#教程
- 2022-02-25 commons-fileupload文件上傳的時候寫入圖片無數據
- 2023-04-17 Linux命令學習之用戶切換su,sudo命令詳解_linux shell
- 2022-02-19 Android~日志工具Log
- 2022-05-09 Python使用Plotly繪制常見5種動態交互式圖表_python
- 2022-08-16 PostgreSQL怎么創建分區表詳解_PostgreSQL
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支