这篇文章主要为大家分析了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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。