我在MFC中使用::AfxBeginThread时遇到问题。
我试着制作一个线程,这就是我的代码。
void CMyoControllerView::OnCbnSelchangeComboFist()
{
int nIndex = m_combo_Fist.GetCurSel();
int INDEX;
if(nIndex != CB_ERR){
CString str;
m_combo_Fist.GetLBText(nIndex, str);
if(str == "Left Click") {
INDEX = 0;
} else if(str == "Double Click") {
INDEX = 1;
} else if(str == "Right Click") {
INDEX = 2;
} else if(str == "Wheel Click") {
INDEX = 3;
} else {
INDEX = 4;
}
pThread_Fist = ::AfxBeginThread(ThreadFunc, &INDEX);
}
}
ThreadFunc函数是…
UINT CMyoControllerView::ThreadFunc(LPVOID pParam)
{
int index= (int)pParam;
if(index == 0) { }
else if(index == 1) { }
...
}
在:AfxBeginThread(ThreadFunc,&INDEX((;
我想将一个参数传递给"INDEX"(可能的值:0~4(。
然而,当我调试这段代码时,ThreadFunc中的"index"变量中有垃圾值。(该值应为0~4。(
我试着使用relpret_cast、relpret_ast等等。但我不能得到正确的价值。
我应该更改什么才能在"index"变量中获得正确的值?
(附言。我不确定,但我认为这可能是x64或x86的问题。所以我在谷歌上搜索了一下,一无所获。(。我使用的是Windows 8 x64。(
传递参数INDEX
的方式很好。您遇到的问题是同步:INDEX
是一个自动变量,当它超出范围时,即在CMyoControllerView::OnCbnSelchangeComboFist
返回之前,它将变为无效。这时,线程可能还没有读取变量,一旦读取,就会看到垃圾。此外,在尝试读取int*
时,您将其重新解释为int
值,因此index
变量是INDEX
变量地址的数值。
解决方案是实现同步。在请求创建一个新线程后,您必须等待它读取传递给它的数据。一种解决方案是使用事件。
创建全局事件对象以同步线程启动:
HANDLE g_hThreadRunning = ::CreateEvent( NULL, FALSE, FALSE, NULL );
更改线程创建代码以等待线程发出信号,表明已完成读取数据(WaitForSingleObject(:
void CMyoControllerView::OnCbnSelchangeComboFist() {
// ...
pThread_Fist = ::AfxBeginThread( ThreadFunc, &INDEX );
::WaitForSingleObject( g_hThreadRunning, INFINITE );
}
在线程过程中,在读取数据(SetEvent(后,将同步对象设置为signaled。请注意,当您传递参数时,您必须以相同的方式解释pParam
,即int*
:
UINT CMyoControllerView::ThreadFunc( LPVOID pParam ) {
int index = *static_cast<int*>( pParam );
::SetEvent( g_hThreadRunning );
if(index == 0) { }
else if(index == 1) { }
// ...
}
另一种选择是让
pParam
指针参数携带int
:
pThread_Fist = ::AfxBeginThread( ThreadFunc, reinterpret_cast<void*>( INDEX ) );
ThreadFunc
:内部
int index = reinterpret_cast<int>( pParam );
由于这是通过值传递参数,因此不需要任何同步。然而,这并不普遍适用。特别是,它可能会在某些平台上失败。它不能保证工作(尽管它适用于今天运行Windows的所有平台(。
通过值转换将INDEX
传递给LPVOID
:
pThread_Fist = ::AfxBeginThread(ThreadFunc, (LPVOID)INDEX);
您现有的线程代码可以进行相反的铸造:
UINT CMyoControllerView::ThreadFunc(LPVOID pParam)
{
int index= (int)pParam;
...
}
对于x86和x64平台,LPVOID
大小足以包含一个整数值。