使用:: AfxBeginThread(ThreadFunc,& INDEX)时如何传递参数;

时间:2015-05-28 08:12:14

标签: c++ multithreading mfc

我在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。)

2 个答案:

答案 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平台的整数值。