我在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。)
我尝试使用reinterpret_cast,reinterpret_cast等。 但我无法获得正确的价值。
我应该更改什么才能在“index”变量中获得正确的值?
(ps。我不确定,但我认为它可能是x64或x86问题。所以我搜索谷歌并没有得到任何结果。 我使用的是Windows 8 x64。)
答案 0 :(得分:1)
你传递参数INDEX
的方式很好。遇到的问题是同步:INDEX
是一个自动变量,当它超出范围时,即在CMyoControllerView::OnCbnSelchangeComboFist
返回之前变为无效。此时你的线程可能没有读取变量,一旦它,它就会看到垃圾。另外,在尝试阅读时,您会将int*
重新解释为int
值,因此index
变量是INDEX
地址的数值变量。
解决方案是实现同步。请求创建新线程后,您必须等待它读取传递给它的数据。一种解决方案是使用事件。
创建一个全局event对象来同步线程启动:
HANDLE g_hThreadRunning = ::CreateEvent( NULL, FALSE, FALSE, NULL );
更改您的线程创建代码以等待线程发出信号,它已完成读取数据(WaitForSingleObject):
void CMyoControllerView::OnCbnSelchangeComboFist() {
// ...
pThread_Fist = ::AfxBeginThread( ThreadFunc, &INDEX );
::WaitForSingleObject( g_hThreadRunning, INFINITE );
}
在线程过程中,在完成读取数据(SetEvent)后,将同步对象设置为信号。请注意,您必须按照与传递参数时相同的方式解释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 今天的所有平台)。
答案 1 :(得分:0)
通过值转换INDEX
传递给LPVOID
:
pThread_Fist = ::AfxBeginThread(ThreadFunc, (LPVOID)INDEX);
现有的线程代码可以进行相反的转换:
UINT CMyoControllerView::ThreadFunc(LPVOID pParam)
{
int index= (int)pParam;
...
}
LPVOID
大小足以包含x86和x64平台的整数值。