您的位置:首页 > 编程语言 > C语言/C++

[C/C++]建议在异步调用的函数的Callback中预留UserData参数

2009-11-01 23:57 429 查看
有时候会碰到一些的C++程序员定义的异步函数(通过Callback通知)没有UserData参数,这样会给OO设计带来很大的麻烦。举个例子(只是例子,不讨论有没有必要作成异步函数):

typedef void (*PFCALLBACK)();

DWORD WorkingFunc(LPVOID* param)

{

// Do something...

PFCALLBACK pFun = (PFCALLBACK)param;

pFun ();
return 0;

}

void Asynchronous(PFCALLBACK pCallbak)

{

HANDLE hThrd = CreateThread(NULL, 0, WorkingFunc, pCallbak, 0, NULL);

CloseHandle(hThrd );

}

如果要调用Asynchronous这个函数,通常可以这么做:

class myClass

{

public:

static void myCallback();

void myFunction();

private:

static HANDLE m_hEvent;

};

HANDLE myClass::m_hEvent= NULL:

void myClass::myCallback()

{

SetEvent(m_hEvent);

}

void myClass::myFunction()

{

m_hEvent= CreateEvent(NULL, FALSE, FALSE, NULL);

Asynchronous(myCallback);

// Do some thing

WaitForSingleObject(m_hEvent, INFINITE);

CloseHandle(m_hEvent);

m_hEvent = NULL;

}

由于m_hEvent是静态成员变量,所有的类的对象都共用一个m_hEvent,所以当这些对象在不同线程中被调用时就可能造成错误!

所以,我们在设计使用Callback的异步函数时,应该预留UserData参数,这样,代码变成以下方式:

typedef void (*PFCALLBACK)(void* UserData);

struct ThreadParam

{

PFCALLBACK pCallback;

void* UserData;

};

DWORD WorkingFunc(LPVOID param)

{

// Do something...

ThreadParam* pParam = (ThreadParam*)param;

pParam->pCallback(pParam->UserData);

delete pParam;
return 0;

}

void Asynchronous(PFCALLBACK pCallbak, void* UserData)

{

ThreadParam *pParam = new ThreadParam;

pParam ->pCallback = pCallbak;

pParam ->UserData = UserData;

HANDLE hThrd = CreateThread(NULL, 0, WorkingFunc, pParam , 0, NULL);

CloseHandle(hThrd);

}

而myClass可以实现成:

class myClass

{

public:

static void myCallback(void* UserData);

void myFunction();

};

void myClass::myCallback(void* UserData)

{

HANDLE hHandle = (HANDLE)UserData

SetEvent(hHandle);

}

void myClass::myFunction()

{

HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

Asynchronous(myCallback, hEvent);

// Do some thing

WaitForSingleObject(hEvent, INFINITE);

CloseHandle(hEvent);

}

由于去掉了静态成员变量,所以在多线程的环境下也能保证正确工作。

大家可以去参考微软的Callback的设计,几乎都留了UserData或者类似的参数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: