網站首頁 編程語言 正文
背景
前些天遇到一個需求,在沒有第三方源碼的情況下,刷新一個第三方UI,并且攔截到其ajax請求的返回結果。當結果為AVALIABLE的時候,停止刷新并語音提示,否則繼續(xù)刷新。
分析這個需求,發(fā)現(xiàn)需要控制一個刷新循環(huán)的暫停與開始,因此網上搜到了通過ManualResetEvent實現(xiàn)線程的暫停與恢復。
ManualResetEvent介紹
ManualResetEvent是一個通過信號機制,實現(xiàn)線程間狀態(tài)同步的類。常用的方法有以下三個:
- WaitOne:阻止當前線程,直到收到信號
- Reset:將事件狀態(tài)設置為非終止狀態(tài),導致線程阻止
- Set:將事件狀態(tài)設置為終止狀態(tài),從而允許繼續(xù)執(zhí)行一個或多個等待線程
實現(xiàn)設計
1.通過CefSharp的谷歌瀏覽器插件請求第三方網站
?2.具體交互邏輯如下
默認開啟一個線程,并通過WaitOne掛起,等待手動開始自動刷新的指令
手動通過Set方法發(fā)送開始工作信號
執(zhí)行完面操作后,通過Reset將線程再次掛起,并等待Ajax結果,判斷Ajax結果,如果不等于AVALIABLE則再次恢復線程
? ? ? ? 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.默認掛起線程,等待信號 ? ? ? ? ? ? ? ? chromiumWebBrowser1.GetBrowser().MainFrame.ExecuteJavaScriptAsync(@"document.evaluate(""http://*[@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(""http://*[@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í)行完相應操作則再次掛起線程,等待ajax請求結果再判斷是否恢復線程 ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? 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ā)送信號恢復線程,讓其工作 ? ? ? ? ? ? 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) ? ? ? ? { ? ? ? ? ? ? // 先調用基類的實現(xiàn),斷點調試 ? ? ? ? ? ? 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請求之后,如果結果不是AVALIABLE則通過StartListenFunc再次恢復線程
? ? 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方法再次恢復了線程對ui的重復查詢
? ? ? ? public static void StartListenFunc() ? ? ? ? { ? ? ? ? ? ? _eventBeginListenWorkList.Set(); ? ? ? ? ? ? StartListen = true; ? ? ? ? }
ManualResetEvent官方介紹如下
https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.manualresetevent?view=netframework-1.1
原文鏈接:https://www.cnblogs.com/chenyishi/p/15825163.html
相關推薦
- 2022-04-24 python自定義封裝帶顏色的logging模塊_python
- 2022-04-07 React中代碼分割的4種實現(xiàn)方式_React
- 2022-04-10 微信小程序canvas drawImage 圖片展示的方法
- 2022-12-19 Python?完美解決?Import?“模塊“?could?not?be?resolved?...的
- 2023-01-19 Oracle查詢表空間大小及每個表所占空間的大小語句示例_oracle
- 2022-04-16 pycharm如何為函數(shù)插入文檔注釋_python
- 2022-01-13 使用element插件中Descriptions遇到的坑
- 2022-10-21 使用nginx進行負載均衡的搭建全過程_nginx
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支