您好,登錄后才能下訂單哦!
這篇文章主要為大家分析了C#中ManualResetEvent如何實現線程的暫停與恢復的相關知識點,內容詳細易懂,操作細節合理,具有一定參考價值。如果感興趣的話,不妨跟著跟隨小編一起來看看,下面跟著小編一起深入學習“C#中ManualResetEvent如何實現線程的暫停與恢復”的知識吧。
前些天遇到一個需求,在沒有第三方源碼的情況下,刷新一個第三方UI,并且攔截到其ajax請求的返回結果。當結果為AVALIABLE的時候,停止刷新并語音提示,否則繼續刷新。
分析這個需求,發現需要控制一個刷新循環的暫停與開始,因此網上搜到了通過ManualResetEvent實現線程的暫停與恢復。
ManualResetEvent是一個通過信號機制,實現線程間狀態同步的類。常用的方法有以下三個:
WaitOne:阻止當前線程,直到收到信號
Reset:將事件狀態設置為非終止狀態,導致線程阻止
Set:將事件狀態設置為終止狀態,從而允許繼續執行一個或多個等待線程
1.通過CefSharp的谷歌瀏覽器插件請求第三方網站
2.具體交互邏輯如下
默認開啟一個線程,并通過WaitOne掛起,等待手動開始自動刷新的指令
手動通過Set方法發送開始工作信號
執行完面操作后,通過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.停止自動監聽ToolStripMenuItem.Enabled = false; } private async void BeginListenWorkerAsync() { while (true) { _eventBeginListenWorkList.WaitOne(); //1.默認掛起線程,等待信號 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.頁面執行完相應操作則再次掛起線程,等待ajax請求結果再判斷是否恢復線程 } } private void 停止自動監聽ToolStripMenuItem_Click(object sender, EventArgs e) { this.開始自動監聽ToolStripMenuItem.Enabled = true; this.停止自動監聽ToolStripMenuItem.Enabled = false; _eventBeginListenWorkList.Reset(); StartListen = false; } private void 開始自動監聽ToolStripMenuItem_Click(object sender, EventArgs e) { this.開始自動監聽ToolStripMenuItem.Enabled = false; this.停止自動監聽ToolStripMenuItem.Enabled = true; _eventBeginListenWorkList.Set(); // 2.手動通過Set發送信號恢復線程,讓其工作 StartListen = true; }
3.現在我們需要定義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) { // 先調用基類的實現,斷點調試 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; }
C#是一個簡單、通用、面向對象的編程語言,它由微軟Microsoft開發,繼承了C和C++強大功能,并且去掉了一些它們的復雜特性,C#綜合了VB簡單的可視化操作和C++的高運行效率,以其強大的操作能力、優雅的語法風格、創新的語言特性和便捷的面向組件編程從而成為.NET開發的首選語言,但它不適用于編寫時間急迫或性能非常高的代碼,因為C#缺乏性能極高的應用程序所需要的關鍵功能。
關于“C#中ManualResetEvent如何實現線程的暫停與恢復”就介紹到這了,更多相關內容可以搜索億速云以前的文章,希望能夠幫助大家答疑解惑,請多多支持億速云網站!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。