RegisterWaitForSingleObject的使用
参考:
5天不再惧怕多线程——第五天 线程池
ThreadPool基础之RegisterWaitForSingleObject
意图:可控制的线程池
贴一段chrome的封装代码
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.#include "base/win/object_watcher.h"#include "base/bind.h" #include "base/logging.h"namespace base { namespace win {//-----------------------------------------------------------------------------ObjectWatcher::ObjectWatcher(): weak_factory_(this),object_(NULL),wait_object_(NULL),origin_loop_(NULL) { }ObjectWatcher::~ObjectWatcher() {StopWatching(); }bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) {CHECK(delegate);if (wait_object_) {NOTREACHED() << "Already watching an object";return false;}// Since our job is to just notice when an object is signaled and report the// result back to this thread, we can just run on a Windows wait thread.DWORD wait_flags = WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE;// DoneWaiting can be synchronously called from RegisterWaitForSingleObject,// so set up all state now.callback_ = base::Bind(&ObjectWatcher::Signal, weak_factory_.GetWeakPtr(),delegate);object_ = object;origin_loop_ = MessageLoop::current();if (!RegisterWaitForSingleObject(&wait_object_, object, DoneWaiting,this, INFINITE, wait_flags)) {NOTREACHED() << "RegisterWaitForSingleObject failed: " << GetLastError();object_ = NULL;wait_object_ = NULL;return false;}// We need to know if the current message loop is going away so we can// prevent the wait thread from trying to access a dead message loop.MessageLoop::current()->AddDestructionObserver(this);return true; }bool ObjectWatcher::StopWatching() {if (!wait_object_)return false;// Make sure ObjectWatcher is used in a single-threaded fashion.DCHECK(origin_loop_ == MessageLoop::current());// Blocking call to cancel the wait. Any callbacks already in progress will// finish before we return from this call.if (!UnregisterWaitEx(wait_object_, INVALID_HANDLE_VALUE)) {NOTREACHED() << "UnregisterWaitEx failed: " << GetLastError();return false;}weak_factory_.InvalidateWeakPtrs();object_ = NULL;wait_object_ = NULL;MessageLoop::current()->RemoveDestructionObserver(this);return true; }HANDLE ObjectWatcher::GetWatchedObject() {return object_; }// static void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) {DCHECK(!timed_out);// The destructor blocks on any callbacks that are in flight, so we know that// that is always a pointer to a valid ObjectWater.ObjectWatcher* that = static_cast<ObjectWatcher*>(param);that->origin_loop_->PostTask(FROM_HERE, that->callback_);that->callback_.Reset(); }void ObjectWatcher::Signal(Delegate* delegate) {// Signaling the delegate may result in our destruction or a nested call to// StartWatching(). As a result, we save any state we need and clear previous// watcher state before signaling the delegate.HANDLE object = object_;StopWatching();delegate->OnObjectSignaled(object); }void ObjectWatcher::WillDestroyCurrentMessageLoop() {// Need to shutdown the watch so that we don't try to access the MessageLoop// after this point.StopWatching(); }} // namespace win } // namespace base
测试代码:
// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.#include <process.h>#include "base/message_loop.h" #include "base/win/object_watcher.h" #include "testing/gtest/include/gtest/gtest.h"namespace base { namespace win {namespace {class QuitDelegate : public ObjectWatcher::Delegate {public:virtual void OnObjectSignaled(HANDLE object) {MessageLoop::current()->Quit();} };class DecrementCountDelegate : public ObjectWatcher::Delegate {public:explicit DecrementCountDelegate(int* counter) : counter_(counter) {}virtual void OnObjectSignaled(HANDLE object) {--(*counter_);}private:int* counter_; };void RunTest_BasicSignal(MessageLoop::Type message_loop_type) {MessageLoop message_loop(message_loop_type);ObjectWatcher watcher;EXPECT_EQ(NULL, watcher.GetWatchedObject());// A manual-reset event that is not yet signaled.HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);QuitDelegate delegate;bool ok = watcher.StartWatching(event, &delegate);EXPECT_TRUE(ok);EXPECT_EQ(event, watcher.GetWatchedObject());SetEvent(event);MessageLoop::current()->Run();EXPECT_EQ(NULL, watcher.GetWatchedObject());CloseHandle(event); }void RunTest_BasicCancel(MessageLoop::Type message_loop_type) {MessageLoop message_loop(message_loop_type);ObjectWatcher watcher;// A manual-reset event that is not yet signaled.HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);QuitDelegate delegate;bool ok = watcher.StartWatching(event, &delegate);EXPECT_TRUE(ok);watcher.StopWatching();CloseHandle(event); }void RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) {MessageLoop message_loop(message_loop_type);ObjectWatcher watcher;int counter = 1;DecrementCountDelegate delegate(&counter);// A manual-reset event that is not yet signaled.HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);bool ok = watcher.StartWatching(event, &delegate);EXPECT_TRUE(ok);SetEvent(event);// Let the background thread do its businessSleep(30);watcher.StopWatching();MessageLoop::current()->RunAllPending();// Our delegate should not have fired.EXPECT_EQ(1, counter);CloseHandle(event); }void RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) {// Simulate a MessageLoop that dies before an ObjectWatcher. This ordinarily// doesn't happen when people use the Thread class, but it can happen when// people use the Singleton pattern or atexit.HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL); // not signaled{ObjectWatcher watcher;{MessageLoop message_loop(message_loop_type);QuitDelegate delegate;watcher.StartWatching(event, &delegate);}}CloseHandle(event); }} // namespace//-----------------------------------------------------------------------------TEST(ObjectWatcherTest, BasicSignal) {RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT);RunTest_BasicSignal(MessageLoop::TYPE_IO);RunTest_BasicSignal(MessageLoop::TYPE_UI); }TEST(ObjectWatcherTest, BasicCancel) {RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT);RunTest_BasicCancel(MessageLoop::TYPE_IO);RunTest_BasicCancel(MessageLoop::TYPE_UI); }TEST(ObjectWatcherTest, CancelAfterSet) {RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT);RunTest_CancelAfterSet(MessageLoop::TYPE_IO);RunTest_CancelAfterSet(MessageLoop::TYPE_UI); }TEST(ObjectWatcherTest, OutlivesMessageLoop) {RunTest_OutlivesMessageLoop(MessageLoop::TYPE_DEFAULT);RunTest_OutlivesMessageLoop(MessageLoop::TYPE_IO);RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI); }} // namespace win } // namespace base
转载于:https://www.cnblogs.com/Clingingboy/archive/2013/03/12/2956245.html
RegisterWaitForSingleObject的使用相关推荐
- ThreadPool基础之RegisterWaitForSingleObject
首先我们看一下它的原型: public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObj ...
- 关于ThreadPool.RegisterWaitForSingleObject和WaitHandle的应用介绍
最近在学习线程相关的内容,所以把学习过程中的心得记录下来,相信大家常用 ThreadPool.QueueUserWorkItem()或者Thread thd=new Thread(new Thread ...
- WCF优化的几个常规思路
前几天用WCF做项目时发现了一个效率问题,由于系统对效率要求较高,困扰了很长时间终于将问题解决了,写下来为以后的兄弟们参考,第一次写博客有不准确的地方还望同行们多喷多指点,先行谢过啦... 问题场景是 ...
- C#如何判断线程池中所有的线程是否已经完成(转)
其 实很简单用ThreadPool.RegisterWaitForSingleObject方法注册一个定时检查线程池的方法,在检查线程的方法内调用 ThreadPool.GetAvailableThr ...
- C#并行开发_Thread/ThreadPool, Task/TaskFactory, Parallel
大家好,本次讨论的是C#中的并行开发,给力吧,随着并行的概念深入,哥也赶上这个潮流了,其实之前讨论C#的异步调用或者C#中BeginInvoke或者Invoke都已经涉及了部分本篇的内容. 参考书目: ...
- Google Breakpad 完全解析(二) —— Windows前台实现篇
原创文章,转载请标明出处:Soul Apogee (http://bigasp.com),谢谢. 好,看完了如何使用breakpad,我们现在看看breakpad在Windows下到底是如何实现的呢? ...
- .NET多线程编程入门
在.NET多线程编程这个系列我们讲一起来探讨多线程编程的各个方面.首先我将在本篇文章的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述.NET平台上多线程编程的知 ...
- 在.NET客户端程序中使用多线程
在.NET客户端程序中使用多线程通常认为在编写程序中用到多线程是一个高级的编程任务,容易发生错误.在本月的栏目中,我将在一个Windows窗体应用程序中使用多线程,它具有实际的意义,同时尽量使事情简单 ...
- 线程池 And 线程池的使用(基于.net平台)
多线程可以提高应用程序的效率,这是肯定的,但是,效率是不是最优的呢,是不是觉得多线程很复杂呢? 前面学习线程的知道,用多线程需要CreateThread创建线程,还要关闭线程.另外,多线程有时候还要对 ...
- C#多线程编程介绍——使用thread、threadpool、timer
C#多线程编程介绍--使用thread.threadpool.timer 在system.threading 命名空间提供一些使得能进行多线程编程的类和接口,其中线程的创建有以下三种方法:thread ...
最新文章
- 字体渲染 mac linux,Mac下通过命令来渲染字体
- viewport实现html页面动态缩放/meta viewport/viewport
- python列表写入csv文件_将多个列表写入csv。Python中的文件
- 【Java】BigDecimal
- TestNG中的参数化– DataProvider和TestNG XML(带有示例)
- 有源蜂鸣器和无源蜂鸣器的区别_电磁式蜂鸣器和压电式蜂鸣器的区别以及驱动方法...
- 飞鸽传书2007程序语言的面向对象最后会成自然语言吗?
- 基于Fabric的性能测试与调优实践
- 程序员是制造 Bug 的“元凶”?
- gcc/g++ 的参数总结(二)
- C++ 自旋锁简单实现
- Three.js案例分析系列1--webgl_animation_cloth 草坪上漂浮的白布
- 基于生物特征识别认证方式对应2020版《个人信息安全规范》的解读-1
- JavaScript中this的绑定
- 将分子SMILES生成DGLGraph
- matplotlib画圆
- Markdown 书写规范
- 好好吃饭,才是最大的教养
- Nginx 对俄罗斯动手了。。。
- 华为手机备忘录资料备份
热门文章
- ScheduledExecutorService 延迟 / 周期执行线程池
- 阶段3 1.Mybatis_05.使用Mybatis完成CRUD_7 Mybatis中参数的深入-使用实体类的包装对象作为查询条件...
- default value of template parameter c++
- ubuntu 16.04 + zabbix 3.4 + postgresql shell
- 支付宝新漏洞引发恐慌,那如何关闭小额免密支付呢
- 实验七——Web应用测试(bookstore项目上完成)
- 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】
- Number of failed login attempts exceeds threshold value
- 数据库操作(不断更新)
- Spring mvc文件下载