windows 创建线程不接受成员函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2891926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:30:26  来源:igfitidea点击:

Create thread is not accepting the member function

c++windowscallbackfunction-pointers

提问by prabhakaran

I am trying to create a class for network programming. This will create a general purpose socket with thread.

我正在尝试为网络编程创建一个类。这将创建一个带有线程的通用套接字。

But when I tried to crete the thread using createthread(). The third argument is producing errors. And from the net I came to know that I can't use the member functions as an argument to the createthread().

但是当我尝试使用 createthread() 来创建线程时。第三个论点是产生错误。从网上我开始知道我不能使用成员函数作为 createthread() 的参数。

Is there any thing by which I can achieve this?

有什么办法可以让我做到这一点吗?

采纳答案by prabhakaran

At lost I got it, the very fact is, in CreateThreadif you pass the socketthen there is no trouble. Because CreateThreadis taking careof that socket. But if you pass as an object which is having that socket, then CreateThreadis not taking careof the socket, and it is ends up in invalid socketin the new thread.

我迷路了,事实是,在CreateThread 中,如果您通过套接字,则没有问题。因为CreateThread的照顾那的插座。但是,如果你通过为它具有一个对象插座,然后CreateThread的不照顾的的插座,这是结束了在无效的套接字新线程

The successed code below

成功代码如下

SOCKET s=socket(....);
bind(s,...);
listen(s,...);
SOCKET temp=accept(s,(sockaddr *)&addrNew,&size);
DWORD threadId;
HANDLE thread=CreateThread(NULL,0,&MyThreadFunction,(LPVOID)(temp),0,&threadId);

回答by SoapBox

The easiest way to handle this is to create a "stub" function which calls back into your class.

处理这个问题的最简单方法是创建一个“存根”函数,它会回调到您的类中。

UINT tid
HANDLE hThread = CreateThread(NULL, 0, myThreadStub, this, 0, &tid);

....

unsigned long WINAPI myThreadStub(void *ptr) 
{
    if (!ptr) return -1;
    return ((MyClass*)ptr)->ThreadMain();
}

CreateThread() allows you to pass an argument to the thread function (parameter 4 of the CreateThread() call). You can use this to pass a pointer to your class. You can then have the thread stub cast that pointer back into the proper type and then call a member function. You can even have "myThreadStub" be a staticmember of "MyClass", allowing it to access private members and data.

CreateThread() 允许您将参数传递给线程函数(CreateThread() 调用的参数 4)。你可以使用它来传递一个指向你的类的指针。然后,您可以让线程存根将该指针转换回正确的类型,然后调用成员函数。您甚至可以让“myThreadStub”成为“MyClass”的静态成员,允许它访问私有成员和数据。

If you have boost installed, you may be able to use boost::bind to do this without creating a stub function. I've never tried that on windows, so I can't say for sure it would work (because the callback function must be a WINAPI call) but if it does work it would look something like:

如果您安装了 boost,您可以使用 boost::bind 来做到这一点,而无需创建存根函数。我从来没有在 Windows 上尝试过,所以我不能肯定它会起作用(因为回调函数必须是一个 WINAPI 调用)但如果它起作用,它看起来像:

HANDLE hThread = CreateThread(NULL, 0, boost::bind(&MyClass::ThreadFunction, this), NULL, 0, &tid);

Where thread function is a non-static member function which takes a single void * argument.

其中线程函数是一个非静态成员函数,它采用单个 void * 参数。

回答by Yevhen Pavliuk

There's an easy way to solve the problem.

有一个简单的方法可以解决这个问题。

Take a look at ThreadProc callback function:

看看ThreadProc 回调函数

    DWORD WINAPI ThreadProc(
      __in  LPVOID lpParameter
    );

And now at CreateThread function:

现在在CreateThread 函数

    HANDLE WINAPI CreateThread(
      __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
      __in       SIZE_T dwStackSize,
      __in       LPTHREAD_START_ROUTINE lpStartAddress,
      __in_opt   LPVOID lpParameter,
      __in       DWORD dwCreationFlags,
      __out_opt  LPDWORD lpThreadId
    );

Use a static method as thread procedure, but call it from a member method, and pass the object pointer to it:

使用静态方法作为线程过程,但从成员方法调用它,并将对象指针传递给它:

    #include <windows.h>

    class MyClass {
     public:
      void CreateThreadForObject() {
        LPSECURITY_ATTRIBUTES security_attributes = 0;
        SIZE_T stack_size = 0;
        LPTHREAD_START_ROUTINE start_routine = &MyClass::ThreadProcForObject;
        LPVOID param = this;
        DWORD creation_flags = 0;
        LPDWORD thread_id = 0;
        CreateThread(security_attributes, stack_size, start_routine, param,
                     creation_flags, thread_id);
      }

     private:
      static DWORD WINAPI ThreadProcForObject(LPVOID param) {
        MyClass* instance = reinterpret_cast<MyClass*>(param);
        if (!instance) return 1;
        // ...
        return 0;
      }
    };

Sorry, I just don't have enough time to write a good example. But I think you understand the way.

抱歉,我只是没有足够的时间来写一个好的例子。但我想你明白这个道理。