[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或者类似的参数。
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或者类似的参数。
相关文章推荐
- lua脚本语言的学习-----------------如何实现c++无参数的函数在lua中调用
- c#调用c++封装dll 参数为字符串输出函数的解决办法
- C++中函数调用时的三种参数传递方式
- C# CallBack异步调用的参数及返回值
- 函数调用约定(注意c++普通函数成员调用时有this参数)
- C++关于参数为const引用类型的函数调用参数成员函数的一个问题
- c/c++/java,函数调用的参数的传递方法
- C# 调用Dll中非托管C++代码时,函数参数的类型对照
- C/C++学习之C提高----函数调用模型、指针做函数参数、字符串的基本操作、一级指针内存模型建立
- PB菜单带参数调用父窗口&父datawindow事件或函数
- c++动态绑定与静态绑定中的函数调用与函数缺省参数
- C# 调用Dll中非托管C++代码时,函数参数的类型对照
- C# 调用Dll中非托管C++代码时,函数参数的类型对照
- C++中函数调用时的三种参数传递方式
- c++调用python函数时,使用PyArray_SimpleNewFromData(nd, dims, typenum, data)函数时出现内存错误的问题
- C# 调用Dll中非托管C++代码,函数参数的类型对照
- C/C++中可变参数的原理 与函数调用约定
- C#中调用C++的dll的参数为指针类型的导出函数(包括二级指针的情况)
- my_mouse_callback”: 函数调用缺少参数列表
- c++ 宏定义调用不定参数的函数