主要使用BeginInvoke方法和ManualResetEvent類(lèi)來(lái)實(shí)現(xiàn)。
成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),安達(dá)企業(yè)網(wǎng)站建設(shè),安達(dá)品牌網(wǎng)站建設(shè),網(wǎng)站定制,安達(dá)網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,安達(dá)網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
BeginInvoke使得函數(shù)在線(xiàn)程池上異步運(yùn)行,運(yùn)行完成后,調(diào)用回調(diào)函數(shù)。
ManualResetEvent用于同步阻塞。
設(shè)計(jì)思想如下:
當(dāng)函數(shù)在線(xiàn)程池中的某一線(xiàn)程上異步的運(yùn)行的時(shí)候,ManualResetEvent阻塞當(dāng)前線(xiàn)程,等待若干時(shí)間。
在等候期間,如果異步函數(shù)運(yùn)行完畢,會(huì)對(duì)ManualResetEvent設(shè)置一個(gè)信號(hào),使得阻塞的線(xiàn)程得以繼續(xù)運(yùn)行下去。
如果等候超時(shí)了,則阻塞的線(xiàn)程也會(huì)取消阻塞,繼續(xù)運(yùn)行下去,但是不再理會(huì)回調(diào)的函數(shù)。(即使回調(diào)函數(shù)仍然被調(diào)用),事實(shí)上,BeginInvoke創(chuàng)建的線(xiàn)程都是后臺(tái)線(xiàn)程,這種線(xiàn)程一但所有的前臺(tái)線(xiàn)程都退出后(其中主線(xiàn)程就是一個(gè)前臺(tái)線(xiàn)程),不管后臺(tái)線(xiàn)程是否執(zhí)行完畢,都會(huì)結(jié)束線(xiàn)程,并退出。因此如果阻塞的主線(xiàn)程完全運(yùn)行完畢退出,那么異步運(yùn)行的線(xiàn)程也會(huì)退出,無(wú)論是否運(yùn)行完畢。
語(yǔ)句isGetSignal = manu.WaitOne(timeout);就是阻塞當(dāng)前線(xiàn)程一段時(shí)間。
該語(yǔ)句阻塞期間,不會(huì)對(duì)isGetSignal賦值,直到阻塞取消后,才會(huì)返回一個(gè)值給isGetSignal。
當(dāng)阻塞是因?yàn)槭盏叫盘?hào)而取消的,得到的值是true。
當(dāng)阻塞是因?yàn)槌瑫r(shí)而取消的,得到的值是false。
整個(gè)流程如下:
把這些代碼邏輯封裝成一個(gè)類(lèi)。
這個(gè)類(lèi)就接受一個(gè)委托和一個(gè)超時(shí)時(shí)間作為構(gòu)造函數(shù)。
把這個(gè)委托和 ManualResetEvent .Set();語(yǔ)句寫(xiě)在一個(gè)方法體內(nèi),CombineActionAndManuset,因此CombineActionAndManuset的調(diào)用就是實(shí)現(xiàn)了方法運(yùn)行完畢后,設(shè)置取消阻塞信號(hào)。
封裝后的代碼:
- public class FuncTimeout
- {
- /// <summary>
- /// 信號(hào)量
- /// </summary>
- public ManualResetEvent manu = new ManualResetEvent(false);
- /// <summary>
- /// 是否接受到信號(hào)
- /// </summary>
- public bool isGetSignal;
- /// <summary>
- /// 設(shè)置超時(shí)時(shí)間
- /// </summary>
- public int timeout;
- /// <summary>
- /// 要調(diào)用的方法的一個(gè)委托
- /// </summary>
- public Action<int> FunctionNeedRun;
- /// <summary>
- /// 構(gòu)造函數(shù),傳入超時(shí)的時(shí)間以及運(yùn)行的方法
- /// </summary>
- /// <param name="_action"></param>
- /// <param name="_timeout"></param>
- public FuncTimeout(Action<int> _action, int _timeout)
- {
- FunctionNeedRun = _action;
- timeout = _timeout;
- }
- /// <summary>
- /// 回調(diào)函數(shù)
- /// </summary>
- /// <param name="ar"></param>
- public void MyAsyncCallback(IAsyncResult ar)
- {
- //isGetSignal為false,表示異步方法其實(shí)已經(jīng)超出設(shè)置的時(shí)間,此時(shí)不再需要執(zhí)行回調(diào)方法。
- if (isGetSignal == false)
- {
- Console.WriteLine("放棄執(zhí)行回調(diào)函數(shù)");
- Thread.CurrentThread.Abort();
- }
- else
- {
- Console.WriteLine("調(diào)用回調(diào)函數(shù)");
- }
- }
- /// <summary>
- /// 調(diào)用函數(shù)
- /// </summary>
- /// <param name="param1"></param>
- public void doAction(int param1)
- {
- Action<int> WhatTodo = CombineActionAndManuset;
- //通過(guò)BeginInvoke方法,在線(xiàn)程池上異步的執(zhí)行方法。
- var r=WhatTodo.BeginInvoke(param1, MyAsyncCallback, null);
- //設(shè)置阻塞,如果上述的BeginInvoke方法在timeout之前運(yùn)行完畢,則manu會(huì)收到信號(hào)。此時(shí)isGetSignal為true。
- //如果timeout時(shí)間內(nèi),還未收到信號(hào),即異步方法還未運(yùn)行完畢,則isGetSignal為false。
- isGetSignal = manu.WaitOne(timeout);
- if (isGetSignal == true)
- {
- Console.WriteLine("函數(shù)運(yùn)行完畢,收到設(shè)置信號(hào),異步執(zhí)行未超時(shí)");
- }
- else
- {
- Console.WriteLine("沒(méi)有收到設(shè)置信號(hào),異步執(zhí)行超時(shí)");
- }
- }
- /// <summary>
- /// 把要傳進(jìn)來(lái)的方法,和 manu.Set()的方法合并到一個(gè)方法體。
- /// action方法運(yùn)行完畢后,設(shè)置信號(hào)量,以取消阻塞。
- /// </summary>
- /// <param name="num"></param>
- public void CombineActionAndManuset(int num)
- {
- FunctionNeedRun(num);
- manu.Set();
- }
- }
測(cè)試代碼:
- class Program
- {
- static void Main(string[] args)
- {
- FuncTimeout ft = new FuncTimeout(dosth, 3000);
- ft.doAction(6);
- }
- static void dosth(int num)
- {
- for (int i = 0; i < num; i++)
- {
- Thread.Sleep(500);
- Console.Write(i);
- }
- }
- }
當(dāng)超時(shí)時(shí)間設(shè)置為5s的時(shí)候,方法未超時(shí)
當(dāng)超時(shí)時(shí)間設(shè)置為1s的時(shí)候,方法超時(shí)
新聞標(biāo)題:C#中,函數(shù)運(yùn)行超時(shí)的功能的實(shí)現(xiàn)
網(wǎng)站URL:http://bm7419.com/article10/psdigo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、用戶(hù)體驗(yàn)、商城網(wǎng)站、網(wǎng)站策劃、企業(yè)建站、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)