【问题标题】:Windows threads - how to make a method a thread function in windows?Windows 线程 - 如何使方法成为 Windows 中的线程函数?
【发布时间】:2011-06-09 15:50:47
【问题描述】:

当然,我不能将指向方法的指针传递给 CreateThread 函数。 我该怎么办?

【问题讨论】:

  • 谨慎使用 CreateThread,因为它不会为新线程初始化 C(可能还有 C++)运行时。
  • 真的吗?如何手动初始化运行时?

标签: c++ windows multithreading winapi pointers


【解决方案1】:

如果使用一个类,像这样的一些模式通常效果很好:

.h

static UINT __cdecl StaticThreadFunc(LPVOID pParam);
UINT ThreadFunc();

.cpp

// Somewhere you launch the thread
AfxBeginThread(
    StaticThreadFunc,
    this);  

UINT __cdecl CYourClass::StaticThreadFunc(LPVOID pParam)
{
    CYourClass *pYourClass = reinterpret_cast<CYourClass*>(pParam);
    UINT retCode = pYourClass->ThreadFunc();

    return retCode;
}

UINT CYourClass::ThreadFunc()
{ 
    // Do your thing, this thread now has access to all the classes member variables
}

【讨论】:

    【解决方案2】:

    我经常这样做:

    class X {
    private:
        static unsigned __stdcall ThreadEntry(void* pUserData) {
            return ((X*)pUserData)->ThreadMain();
        }
    
        unsigned ThreadMain() {
             ...
        }
    };
    

    然后我将this 作为用户数据传递给线程创建函数(_beginthread[ex]、CreateThread 等)

    【讨论】:

      【解决方案3】:

      最常见的方法是创建一个具有 run() 方法和 start() 方法的 Thread 类(这些名称是从 Java Thread 类中借用的)。 run() 是一个纯虚函数,您可以在派生自 Thread 的类中重载它以完成实际工作。 start() 方法在内部调用 CreateThread,通过 reinterpret_cast 将 this 指针传递给 void*。 Thread 类还有一个您传递给 CreateThread 的 threadEntryPoint() 静态函数。在 threadEntryPoint() 中,您执行 reinterpret_cast 回 Thread*,然后对其调用 run()。

      如果有一种情况,您只想在单独的线程上执行另一个类的方法(无需从 Thread 类继承),您可以创建一个接收一对对象+方法指针的 Thread 派生类在构造函数中,并在 run() 中调用它们。为了让事情变得简单,让这个派生类成为一个模板。还可以查看函子适配器的 boost。

      【讨论】:

      • 谢谢。据我了解,我只需要在我的类中添加一个静态函数和一个启动方法,threadEntryPoint 功能将在 statiс 方法中实现。
      • 是的,如果您只想执行一次,就这么简单。如果你想在其他地方重用它,最好将代码隔离在一个单独的类中。
      【解决方案4】:

      CreateThread 不会使用指向成员函数的指针。您可以将成员函数包装在静态函数中,该函数通过 lpParameter 获取对象指针。

      【讨论】:

        【解决方案5】:

        CreateThread 的 lpStartAddress 是 DWORD (WINAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter) 类型,这与成员函数不兼容,因为成员函数在其签名中具有隐式 this 指针。所以创建一个静态函数并将类指针作为参数传递给线程函数。

        【讨论】:

          【解决方案6】:

          如果您在谈论 Native CreateThread 方法,您可能需要执行以下操作

          CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&MyThreadProc,NULL,NULL,&threadId);
          

          你的回调方法被定义为

          void MyThreadProc()
          {
          }
          

          【讨论】:

          • 你不想这样做——这里的强制转换是一个问题:一般来说,你永远不应该为了让事情正常工作而强制转换一个函数。相反,您应该在没有强制转换的情况下传递 MyThreadProc,然后将 void MyThreadProc() 更改为 DWORD WINAPI MyThreadProc(LPVOID),这正是 CreateThread 所期望的。传递具有与 API 预期不同数量或类型的参数或调用约定的函数可能会导致堆栈混乱。
          猜你喜欢
          • 2021-04-04
          • 2011-10-03
          • 1970-01-01
          • 2016-06-09
          • 1970-01-01
          • 1970-01-01
          • 2011-12-05
          • 1970-01-01
          相关资源
          最近更新 更多