溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#中ManualResetEvent如何實現(xiàn)線程的暫停與恢復(fù)

發(fā)布時間:2022-01-20 13:41:13 來源:億速云 閱讀:274 作者:kk 欄目:開發(fā)技術(shù)

這篇文章主要為大家分析了C#中ManualResetEvent如何實現(xiàn)線程的暫停與恢復(fù)的相關(guān)知識點,內(nèi)容詳細(xì)易懂,操作細(xì)節(jié)合理,具有一定參考價值。如果感興趣的話,不妨跟著跟隨小編一起來看看,下面跟著小編一起深入學(xué)習(xí)“C#中ManualResetEvent如何實現(xiàn)線程的暫停與恢復(fù)”的知識吧。

背景

前些天遇到一個需求,在沒有第三方源碼的情況下,刷新一個第三方UI,并且攔截到其ajax請求的返回結(jié)果。當(dāng)結(jié)果為AVALIABLE的時候,停止刷新并語音提示,否則繼續(xù)刷新。

分析這個需求,發(fā)現(xiàn)需要控制一個刷新循環(huán)的暫停與開始,因此網(wǎng)上搜到了通過ManualResetEvent實現(xiàn)線程的暫停與恢復(fù)。

ManualResetEvent介紹

ManualResetEvent是一個通過信號機(jī)制,實現(xiàn)線程間狀態(tài)同步的類。常用的方法有以下三個:

  • WaitOne:阻止當(dāng)前線程,直到收到信號

  • Reset:將事件狀態(tài)設(shè)置為非終止?fàn)顟B(tài),導(dǎo)致線程阻止

  • Set:將事件狀態(tài)設(shè)置為終止?fàn)顟B(tài),從而允許繼續(xù)執(zhí)行一個或多個等待線程

實現(xiàn)設(shè)計

1.通過CefSharp的谷歌瀏覽器插件請求第三方網(wǎng)站

C#中ManualResetEvent如何實現(xiàn)線程的暫停與恢復(fù)

 2.具體交互邏輯如下

默認(rèn)開啟一個線程,并通過WaitOne掛起,等待手動開始自動刷新的指令
手動通過Set方法發(fā)送開始工作信號
執(zhí)行完面操作后,通過Reset將線程再次掛起,并等待Ajax結(jié)果,判斷Ajax結(jié)果,如果不等于AVALIABLE則再次恢復(fù)線程

        public Form1()
        {
            InitializeComponent();
            var setting = new CefSettings();
            setting.Locale = "zh-CN";
            setting.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36";
            // 避免頁面加載不出來, 建議加上這句
            Cef.Initialize(setting);

            workerThread = new Thread(new ThreadStart(BeginListenWorkerAsync));
            workerThread.IsBackground = true;
            workerThread.Start();

            this.停止自動監(jiān)聽ToolStripMenuItem.Enabled = false;
        }

        private async void BeginListenWorkerAsync()
        {
            while (true)
            {
                _eventBeginListenWorkList.WaitOne();  //1.默認(rèn)掛起線程,等待信號
                chromiumWebBrowser1.GetBrowser().MainFrame.ExecuteJavaScriptAsync(@"document.evaluate(""//*[@id='root']/div[1]/div[2]/div/div[2]/div[1]/div[1]/div/div[1]/button"", document).iterateNext().click()");

                Thread.Sleep(1000);
                chromiumWebBrowser1.GetBrowser().MainFrame.ExecuteJavaScriptAsync(@"document.evaluate(""//*[@id='root']/div[1]/div[2]/div/div[1]/div/div/div/div[2]/div[6]/div/button"", document).iterateNext().click()");
                _eventBeginListenWorkList.Reset(); //3.頁面執(zhí)行完相應(yīng)操作則再次掛起線程,等待ajax請求結(jié)果再判斷是否恢復(fù)線程
            }
        }

        private void 停止自動監(jiān)聽ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.開始自動監(jiān)聽ToolStripMenuItem.Enabled = true;
            this.停止自動監(jiān)聽ToolStripMenuItem.Enabled = false;
            _eventBeginListenWorkList.Reset();
            StartListen = false;
        }

        private void 開始自動監(jiān)聽ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.開始自動監(jiān)聽ToolStripMenuItem.Enabled = false;
            this.停止自動監(jiān)聽ToolStripMenuItem.Enabled = true;
            _eventBeginListenWorkList.Set(); // 2.手動通過Set發(fā)送信號恢復(fù)線程,讓其工作
            StartListen = true;
        }

3.現(xiàn)在我們需要定義RequestHandler來指定ResourceHandler攔截ajax請求

        private void Form1_Load(object sender, EventArgs e)
        {
            chromiumWebBrowser1.RequestHandler = new MyRequestHandler(this);
            chromiumWebBrowser1.Load("https://www.xxxxxxxx.com/");
        }

MyRequestHandler中需要指定自定義ResourceHandler

    public class MyRequestHandler : RequestHandler
    {
        Form1 _form;
        public MyRequestHandler(Form1 form)
        {
            _form = form;
        }
        public static string AuthorizationValue;
        protected override bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture,
            bool isRedirect)
        {
            // 先調(diào)用基類的實現(xiàn),斷點調(diào)試
            return base.OnBeforeBrowse(chromiumWebBrowser, browser, frame, request, userGesture, isRedirect);
        }

        protected override IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame,
            IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
        {
            Console.WriteLine(request.Url);
            if (request.Url.StartsWith("https://www.xxxxxxxxxxxxxxxx/api") && request.Headers.AllKeys.Contains("Authorization"))
            {
                AuthorizationValue = request.Headers["Authorization"];
            }

            return new MyResourceRequestHandler(_form);
        }
    }

4.最后ResourceRequestHandler攔截到ajax請求之后,如果結(jié)果不是AVALIABLE則通過StartListenFunc再次恢復(fù)線程

    public class MyResourceRequestHandler : ResourceRequestHandler
    {
        Form1 _form;
        public MyResourceRequestHandler(Form1 form)
        {
            _form = form;
        }
        private Dictionary<ulong, MemoryStreamResponseFilter> responseDictionary = new Dictionary<ulong, MemoryStreamResponseFilter>();
        protected override IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            var dataFilter = new MemoryStreamResponseFilter();
            responseDictionary.Add(request.Identifier, dataFilter);
            return dataFilter;
        }

        protected override void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        {
            MemoryStreamResponseFilter filter;
            if (responseDictionary.TryGetValue(request.Identifier, out filter))
            {
                var data = filter.Data;
                
                if (request.Url.StartsWith("https://xxxxxxxxxxxxxxxxxxxx/oneapi"))
                {
                    var available = false;
                    string s = System.Text.Encoding.UTF8.GetString(data, 0, data.Length);
                    Console.WriteLine(s);
                    if (!string.IsNullOrEmpty(s))
                    {
                        var responseData = JsonConvert.DeserializeObject<ScheduleResponse>(s);
                        if (responseData != null && responseData.productPreviews != null)
                        {
                            foreach (var item in responseData.productPreviews)
                            {
                                if (item.schedule != null && item.schedule.status != null && item.schedule.status.name == "AVAILABLE")
                                {
                                    available = true;
                                    Mp3Player.Play();
                                    Action act = delegate () { _form.StopListen(); };
                                    _form.Invoke(act);
                                    break;
                                }
                            }
                        }
                    }

                    if (!available && Form1.StartListen)
                    {
                        Form1.StartListenFunc();
                    }
                }
                
                filter.Dispose();
            }
        }
    }

 而StartListenFunc則是通過Set方法再次恢復(fù)了線程對ui的重復(fù)查詢

        public static void StartListenFunc()
        {
            _eventBeginListenWorkList.Set();
            StartListen = true;
        }

C#是什么

C#是一個簡單、通用、面向?qū)ο蟮木幊陶Z言,它由微軟Microsoft開發(fā),繼承了C和C++強(qiáng)大功能,并且去掉了一些它們的復(fù)雜特性,C#綜合了VB簡單的可視化操作和C++的高運(yùn)行效率,以其強(qiáng)大的操作能力、優(yōu)雅的語法風(fēng)格、創(chuàng)新的語言特性和便捷的面向組件編程從而成為.NET開發(fā)的首選語言,但它不適用于編寫時間急迫或性能非常高的代碼,因為C#缺乏性能極高的應(yīng)用程序所需要的關(guān)鍵功能。

關(guān)于“C#中ManualResetEvent如何實現(xiàn)線程的暫停與恢復(fù)”就介紹到這了,更多相關(guān)內(nèi)容可以搜索億速云以前的文章,希望能夠幫助大家答疑解惑,請多多支持億速云網(wǎng)站!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI