AfxBeginThread函数参数传递的问题

7 篇文章 1 订阅
5 篇文章 0 订阅

转载自:http://blog.csdn.net/oceanlucy/article/details/7345057


AfxBeginThread函数参数传递的问题

一、背景

最近接手一个软件开发项目,该软件需要同时启动多个线程进行订单作业,而且每个订单可能会处理大批量数据,运行起来时内存占用率有可能会比较大,所以采用多线程作业。同时由于每个线程都会调用某些公用的动态库或全局变量,如果某个动态库不支持多线程调用,如动态库中定义了多个全局变量,则多个线程同时作业时会出现数值错误,所以应该通过函数AfxBeginThread()来进行参数传递,每个线程独自分开处理。

二、AfxBeginThread函数知识

1、AfxBeginThread的原型有两个,一个是用户界面(user-interface)线程,一个是工作者(worker)线程。以下重点介绍工作者线程,其原型如下所示。

CWinThread* AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc, 
LPVOID pParam,
int nPriority, 
UINT nStackSize, 
DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
其中:
参数1 :指向工作者线程的控制函数,其值不能为空,声明方式为UINT MyControllingFunc( LPVOID pParam )。
参数2 :传入到控制函数的参数(pfnThreadProc对应的函数),它的类型为LPVOID
参数3:指定线程的优先级。
参数4:指定新创建线程的堆栈大小(bytes),如果为0,则默认与创建该线程的线程相同。

参数5:是一个创建标识,如果是CREATE_SUSPENDED,则在悬挂状态创建线程,在线程创建后线程挂起,否则如果该值为0,则线程在创建后立即开始线程的执行。
参数6:指定线程的安全属性,如果该值为NULL,则与创建该线程的线程相同。NT下有用。 

返回值:返回新创建的线程指针。

注意:

  • UINT MyControllingFunction( LPVOID pParam )函数必须声明为全局函数或者静态成员函数。
  • 在进行多线程编程时,传入到控制函数里的变量尽可能不要使用全局变量,考虑用参数传入到控制函数中。

三、具体实现

对于线程函数中参数的传递,我们这里定义一个结构体类型,用new运算符申请内存并用该指针来传递。

1、函数和结构体全局声明

UINT MyControllingFunction(LPVOID lpParam);

//transfer parameter to thread

typedef struct SthData 

{

ungsigned char ucOrderNumber[255];

ungsigned char ucOrderID[255];

}*pSthData;

2、结构体赋值

//pass parameters to thread

pSthData pDataValue = new SthData;

memset(pDataValue, 0x00, sizeof(SthData));

memcpy(pDataValue->ucOrderID,  strOrderID.GetBuffer(strOrderID.GetLength()), strOrderID.GetLength());

memcpy(pDataValue->ucOrderNumber,strTask_No.GetBuffer(strTask_No.GetLength()),strTask_No.GetLength());

strOrderID.ReleaseBuffer(-1);

strTask_No.ReleaseBuffer(-1);

//create thread

CWinThread* pThread; 

pThread = AfxBeginThread(MyControllingFunction, pDataValue);

delete stcSthData;

stcSthData = NULL;

3、线程内调用

UINT MyControllingFunction(LPVOID lpParam)

{

SthData* stcSthDataData = (SthData *)lpParam;

strOrderID = stcSthDataData->ucOrderID; 

strOrderNum = stcSthDataData->ucOrderNumber; 

......

......

}

4、结果

点击“运行”按钮后,调试时发现传递进来的参数ucOrderID和ucOrderNumber为乱码,以致于strOrderID和strOrderNum 的值为空。

怎么回事呢?

原来问题就出现在AfxBeginThread(MyControllingFunction, pDataValue)函数后的语句:delete stcSthData。当程序执行到AfxBeginThread(MyControllingFunction, pDataValue)函数这一步时,程序会创建一个进程,并调用MyControllingFunction线程函数,但是同时也会往下执行代码语句,即delete stcSthData。我们知道,用new 运算符可以动态分配内存,而且必须与delete 配对使用。当使用delete运算符时,它会释放撤销刚刚申请的内存地址空间,即会把指向结构体地址所对应的内存释放,导致我们看到的乱码。

5、解决办法

delete stcSthData;

stcSthData = NULL;

应该把以上语句放入到线程函数体内。

UINT MyControllingFunction(LPVOID lpParam)

{

SthData* stcSthDataData = (SthData *)lpParam;

strOrderID = stcSthDataData->ucOrderID; 

strOrderNum = stcSthDataData->ucOrderNumber; 

delete stcSthData;

stcSthData = NULL;  //防止野指针

......

......

}

四、其它

1、线程函数中使用类成员或函数

  • 我们可以把this指针作为参数传递给线程函数,如AfxBeginThread(MyControllingFunction, this)
  • 如果我们不想传递参数,则可以定义一个全局变量CWnd * cwind;然后在初始化函数中把this指针赋给它,如cwind = this;最后在线程函数UINT MyControllingFunction(LPVOID lpParam)中强制进行类型转换,如下所示:
    cwind = this;
    UINT MyControllingFunction(LPVOID lpParam)
    {
    CString strOrderID
    CSthDataDlg *cDlg = (CSthDataDlg *)cwind;
    strOrderID = cDlg->m_strOrderID;
    .......
    .......
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值