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

如何在C++类中安全地使用多线程中的处理函数

2015-08-23 20:04 429 查看
首先我们有必要了解清楚成员函数实际上如何工作的,一个非静态的类成员函数都有一个隐藏起来的参数被推入堆栈之中,当编译器需要处理类的成员变量时,它需要处理类的成员变量时,它需要这个隐藏参数的帮忙。这就是"this"参数。因此,ThreadObject::ThreadObject(LPVOID param)(线程处理函数)事实上有两个参数,一个是this指针,另一个是param.

当操作系统启动一个新线程时,它也为该线程产生一个专用的堆栈。操作系统必须在这一心堆栈中重新产生一个对你的线程函数的调用操作。这也就是为什么线程函数的类型一定要符合_cdecl或WINAPI(也就是_stacall)的原因。BADCLASS当掉的原因就是因为ThreadObject::ThreadFunc预期会有一个this指针,而操作系统只知道把param参数推入新堆栈中。毫不令人惊讶,当然要当掉了。

备注:关于 this 指针,以及下一节将提到的解决方案“静态成员函数”,在《深入浅出 MFC》(侯俊杰著/华中科技大学出版社出版)第2章的“this 指针”一节以及“静态成员”一节有十分深入而详细的说明。该书第6章的“Callback 函数”一节曾举例说明为什么“callback 函一定必须是静态成员函数”,而事实上,线程函数是一个被操作系统调用的函数,正是一个callback函数!

下面正确的贴出代码:

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <process.h>

typedef unsigned (WINAPI *PBEGINTHREADEX_THREADFUNC)
(LPVOID lpThreadParameter);

typedef unsigned *PBEGINTHREADEX_THREADID;

class ThreadObject
{
public:
ThreadObject();
void StartThread();
void WaitForExit();

static DWORD WINAPI ThreadFunc(LPVOID param);

protected:
virtual DWORD ThreadMemberFunc();

HANDLE m_hThread;
DWORD m_ThreadId;
};

ThreadObject::ThreadObject()
{
m_hThread = NULL;
m_ThreadId = 0;
}

void ThreadObject::StartThread()
{
m_hThread = (HANDLE)_beginthreadex(NULL,0,(PBEGINTHREADEX_THREADFUNC)ThreadObject::ThreadFunc,
(LPVOID)this, 0, (PBEGINTHREADEX_THREADID)&m_ThreadId);
if(m_hThread != NULL)
{
printf("Thread launched\n");
}
}

void ThreadObject::WaitForExit()
{
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
}

DWORD WINAPI ThreadObject::ThreadFunc(LPVOID param)
{
ThreadObject* pto = (ThreadObject*)param;

return pto->ThreadMemberFunc();
}

DWORD ThreadObject::ThreadMemberFunc()
{
//std::cout<<"Do Something usefull......."<<endl;
printf("Do Something usefull.......");
return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
//cout<<"hello world!"<<endl;

ThreadObject obj;
obj.StartThread();
obj.WaitForExit();

getchar();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息