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

How to pass an argument when using ::AfxBeginThread(ThreadFunc, &INDEX);

本文关键字:ThreadFunc INDEX AfxBeginThread 何使用 参数      更新时间:2023-10-16

我在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大小足以包含一个整数值。