青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Leo

<2007年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

統計

  • 隨筆 - 2
  • 文章 - 0
  • 評論 - 2
  • 引用 - 0

常用鏈接

留言簿(1)

隨筆檔案

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

How to use SetTimer() with callback to a non-static member function

Quick update...

After reviewing the comments and suggestions from a few people, I made the solution better. Look for an update to this article which uses a better approach, namely using the functions:

  • CreateWaitableTimer()
  • SetWaitableTimer()
  • WaitForMultipleObjects()

The solution based on these functions will allow multiple instances of the CSleeperThread class to run (instead of just one using the current example). So stay tuned, I'll have this article updated as soon as possible. :-)

Introduction

I have seen many questions on the boards about how to properly use SetTimer(). I've also noticed that most of these questions are around how to put a thread to sleep for X seconds. One obvious answer would be to use the Sleep() function. The main drawback is, how do you gracefully shut down your thread, or cancel the Sleep() operation before the time expires.

This article is meant to address all of the above. I give an example of putting a thread to sleep using SetTimer(). The SetTimer() calls back to a non-static function. This is key, because normally you have to pass a static member to SetTimer() which means it can't access any other non-static variables or member functions of the class.

Details

Since implementing a non-static callback member is key to this, we'll go into this first. Implementing a callback to a static member function doesn't require anything different from implementing a regular C callback function. Since static member functions have the same signature as C functions with the same calling conventions, they can be referenced using just the function name.

Making a non-static callback member function is a different story, because they have a different signature than a C function. To make a non-static member function, it requires the use of two additional items:

  • A global (void*) pointer, referencing the class of the callback function
  • A wrapper function which will be passed to SetTimer()

This is actually a fairly simple implementation. First, you need to define your class:

class CSleeperThread : public CWinThread {
public:
static VOID CALLBACK TimerProc_Wrapper( HWND hwnd, UINT uMsg,
UINT idEvent, DWORD dwTime );
VOID CALLBACK TimerProc( HWND hwnd,
UINT uMsg, UINT idEvent, DWORD dwTime );
void ThreadMain();
void WakeUp();
private:
static void * pObject;
UINT_PTR pTimer;
CRITICAL_SECTION lock;
};

Then, don't forget to include the following line in your class implementation file:

void * CSleeperThread::pObject;

Now that we have our class declared, we can look at the wrapper function, the non-static member function and the member function that will call SetTimer():

VOID CALLBACK CSleeperThread::TimerProc_Wrapper( HWND hwnd, UINT uMsg,
UINT idEvent, DWORD dwTime ) {
CSleeperThread *pSomeClass = (CSleeperThread*)pObject; // cast the void pointer
pSomeClass->TimerProc(hwnd, uMsg, idEvent, dwTime); // call non-static function
}

The wrapper function first initializes a CSleeperThread pointer with pObject. Since pSomeClass is a local pointer, we can access it within the static wrapper function.

VOID CALLBACK CSleeperThread::TimerProc(HWND hwnd,
UINT uMsg, UINT idEvent, DWORD dwTime) {
::EnterCriticalSection(&lock);
if(idEvent == pTimer) {
KillTimer(NULL, pTimer);  // kill the timer so it won't fire again
ResumeThread();  // resume the main thread function
}
::LeaveCriticalSection(&lock);
}

The TimerProc member function isn't static, so we can access other non-static functions like ResumeThread() and we can access the private variable lock. Notice that I've entered a critical section which prevents a second timer event to enter the callback, thus ensuring that the first execution of TimerProc() will cancel out the timer.

Next, let's take a look at the main execution function, ThreadMain().

void CSleeperThread::ThreadMain()
{
pObject = this; // VERY IMPORTANT, must be initialized before
// calling SetTimer()
// call SetTimer, passing the wrapper function as the callback
pTimer = SetTimer(NULL, NULL, 10000, TimerProc_Wrapper);
// suspend until the timer expires
SuspendThread();
// the timer has expired, continue processing 
}

The first step in ThreadMain() is absolutely critical. We need to assign the class instance pointer (this) to the pObject variable. This is how the wrapper callback function will gain access to execute the non-static member function.

Next, we just call SetTimer() passing in a function pointer to our wrapper function. SetTimer() will call the wrapper function when the timer expires. The wrapper function in turn, will execute the non-static function TimerProc(), by accessing the static variable pSomeClass.

NOTE: I chose to implement a main function that will create the timer, go to sleep, continue processing and then exit when finished. This is in effect a function that will only execute once per timer. You could easily add a loop to ThreadMain() which would execute once for each timer event.

One last little function. Since we used SuspendThread() in ThreadMain(), if we need to wake up the thread (for whatever reason), all we have to do is make a call to ResumeThread(). So, I've added an access function like so:

void WakeUp() {
::EnterCriticalSection(&lock);
KillTimer(NULL, pTimer);
ResumeThread(); // wake the thread up
}

Buh dee buh dee, that's all folks...

And there we have it. A thread safe class that goes to sleep using SetTimer() and a non-static callback function; which also has the ability to wake up before the timer expires.

Hopefully, you have found this helpful. I've actually used this code in a project I'm working on now, and was in hopes someone else would get some good use out of it.

Someone once told me "you'll like programming if you like banging your head against the wall repeatedly". I've found that to be true, it took me literally several days to figure out what I've put into this article, I'm just slow I guess.

Whew, my head hurts, time for some Advil...or Ibooprofin.. or asssprin.... or something.

Credits...

I probably learned way more in the process of writing this article. So, much thanks goes to Lars Haendel for creating a web-site dedicated to understanding function pointers, without which I wouldn't know didley.

www.function-pointer.org.

posted on 2007-05-16 10:31 LeoChen 閱讀(1658) 評論(0)  編輯 收藏 引用

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            蜜桃精品久久久久久久免费影院| 日韩午夜精品| 久久久久久久高潮| 久久久99免费视频| 亚洲第一中文字幕| 亚洲精品乱码久久久久久蜜桃91| 欧美成人亚洲成人| 一区二区三区精品国产| 亚洲一区二区三区中文字幕| 好男人免费精品视频| 亚洲第一狼人社区| 国产精品美女久久| 美女精品在线| 欧美日韩亚洲综合| 久久亚洲精品伦理| 欧美日本亚洲| 久久精品一区蜜桃臀影院 | 欧美影院成人| 久久夜色精品国产| 亚洲一区久久久| 久久精品亚洲精品| 亚洲香蕉伊综合在人在线视看| 亚洲制服欧美中文字幕中文字幕| 亚洲电影毛片| 亚洲图色在线| 亚洲精品综合| 久久精品中文字幕一区二区三区| 99热在这里有精品免费| 欧美一区二区三区免费大片| 亚洲免费成人| 久久蜜桃精品| 欧美亚洲网站| 欧美日韩精品欧美日韩精品一 | 精品999日本| 国产精品99久久久久久白浆小说| 亚洲国产精品久久久久秋霞不卡 | 免费成人av在线看| 久久久国产精彩视频美女艺术照福利 | 午夜精品久久99蜜桃的功能介绍| 免费在线观看精品| 久久久99久久精品女同性| 欧美日韩精品一二三区| 欧美顶级少妇做爰| 黄色亚洲在线| 性色av一区二区三区红粉影视| 亚洲五月六月| 欧美精品成人| 亚洲国产高清高潮精品美女| 国内精品久久久久影院薰衣草| 中文亚洲免费| 亚洲一区二区三区在线看| 欧美日韩福利视频| 亚洲经典自拍| 亚洲欧洲一区二区天堂久久| 久久综合久久综合这里只有精品| 久久久久久网址| 国产一区二区三区电影在线观看| 亚洲主播在线观看| 欧美怡红院视频| 国产日韩av高清| 午夜精品久久久久久久久| 欧美一级二级三级蜜桃| 国产精品欧美一区喷水| 亚洲一区二区三区四区在线观看| 亚洲自拍16p| 国产伦理一区| 欧美中在线观看| 久久手机免费观看| 亚洲国产欧美日韩另类综合| 麻豆精品一区二区av白丝在线| 蜜桃伊人久久| 亚洲精品九九| 欧美日韩一区二区三区免费| 正在播放欧美一区| 久久精品国产精品亚洲| 狠狠色丁香婷婷综合影院| 久久婷婷综合激情| 亚洲国产精品成人va在线观看| 99精品视频免费| 国产精品久久久久久久第一福利 | 欧美自拍偷拍| 亚洲福利视频三区| 亚洲午夜羞羞片| 国产欧美精品在线观看| 久久只有精品| 日韩亚洲在线观看| 久久精品久久99精品久久| 亚洲大片精品永久免费| 欧美日韩亚洲一区三区 | 午夜欧美精品| 欧美国产在线电影| 亚洲一区日韩在线| 在线精品国产欧美| 欧美视频一区二区三区…| 久久av一区二区三区漫画| 亚洲国产女人aaa毛片在线| 亚洲在线一区二区| 亚洲福利在线观看| 国产精品青草综合久久久久99| 久久精视频免费在线久久完整在线看| 亚洲福利视频三区| 欧美一区二区高清| 日韩一级精品| 尤物yw午夜国产精品视频明星| 欧美精品午夜| 久久久九九九九| 中国成人黄色视屏| 亚洲成人资源| 欧美日韩国产a| 久久久久欧美精品| 亚洲天堂av在线免费观看| 欧美激情精品久久久久久黑人 | 亚洲一区久久久| 91久久精品国产91久久性色| 国产亚洲欧洲一区高清在线观看| 欧美精品国产精品日韩精品| 欧美制服丝袜| 亚洲一区二区三| 亚洲精品一区二区三区四区高清| 久久久久久久性| 欧美一站二站| 亚洲欧美日韩国产中文在线| 亚洲免费观看在线视频| 亚洲第一在线视频| 狠狠色狠狠色综合日日tαg | 欧美成人免费一级人片100| 欧美一区日本一区韩国一区| 亚洲一区不卡| 亚洲视频免费| 宅男噜噜噜66一区二区| 亚洲乱码视频| 亚洲精品在线视频观看| 亚洲人成绝费网站色www| 欧美国产三区| 欧美成人精品在线| 欧美成人精品一区二区| 美女网站久久| 美脚丝袜一区二区三区在线观看| 久久久99国产精品免费| 久久国产成人| 久久精品国产999大香线蕉| 久久国产视频网| 久久久国产一区二区三区| 久久久久久久欧美精品| 久久精品亚洲乱码伦伦中文| 久久久www免费人成黑人精品| 久久成人免费视频| 久久久亚洲国产天美传媒修理工| 欧美一级成年大片在线观看| 久久精品视频免费观看| 六月婷婷一区| 欧美成人免费播放| 亚洲精品免费一区二区三区| 亚洲精品欧美日韩专区| 一区二区三区久久网| 亚洲主播在线观看| 久久久久成人精品| 欧美成人69av| 国产精品播放| 好看不卡的中文字幕| 亚洲黄色一区| 亚洲午夜精品福利| 久久嫩草精品久久久精品| 欧美+日本+国产+在线a∨观看| 欧美激情精品久久久久久免费印度 | 亚洲国产日韩在线一区模特| 亚洲老司机av| 午夜一级久久| 欧美成人dvd在线视频| 亚洲级视频在线观看免费1级| 99视频有精品| 久久久精品国产免大香伊 | 久久久高清一区二区三区| 欧美成人久久| 国产美女精品| 亚洲国内欧美| 欧美在线免费一级片| 欧美激情精品| 亚洲欧美日韩国产精品| 蜜臀久久久99精品久久久久久| 欧美午夜精品一区| 亚洲第一狼人社区| 欧美一级专区| 亚洲精品一区久久久久久| 欧美在线观看一区二区三区| 欧美日韩免费高清| 亚洲国产精品成人| 欧美中文字幕在线| 亚洲看片免费| 免费在线观看一区二区| 国产一区二区三区奇米久涩 | 亚洲无线一线二线三线区别av| 久久露脸国产精品| 亚洲在线黄色| 欧美日韩在线观看一区二区| 亚洲欧洲精品一区二区三区波多野1战4| 校园激情久久| 中文av一区二区| 欧美日韩18| 亚洲欧洲在线免费|