对于属于类成员的函数,如何使用CreateThread ?

时间:2023-01-29 21:13:26

How do you use CreateThread() to create threads of functions which are class members?

如何使用CreateThread()创建属于类成员的函数的线程?

2 个解决方案

#1


62  

You need to create a static method to use as the actual thread start function, and pass a pointer to the instance as the lpParameter argument to CreateThread. That will get passed to the static method, which can cast it to an object pointer and call through to the member function.

您需要创建一个静态方法,将其用作实际的线程启动函数,并将指针作为lpParameter参数传递给该实例,以创建CreateThread。它将传递给静态方法,静态方法可以将它转换为对象指针并调用成员函数。

class MyClass
{
    static DWORD WINAPI StaticThreadStart(void* Param)
    {
        MyClass* This = (MyClass*) Param;
        return This->ThreadStart();
    }

    DWORD ThreadStart(void)
    {
        // Do stuff
    }

    void startMyThread()
    {
       DWORD ThreadID;
       CreateThread(NULL, 0, StaticThreadStart, (void*) this, 0, &ThreadID);
    }
};

#2


9  

Others who come across, might want to use my solution. It's a complete Source File compiled with VS2008. See below for a short instruction example on how to use!

其他遇到的人可能想用我的解决方案。它是用VS2008编译的一个完整的源文件。下面是一个关于如何使用的简短说明示例!

// Thread.h
#ifndef __THREAD_H__
#define __THREAD_H__
// #############################################################################
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// =============================================================================
template<class T>
class Thread
{
    // new type Method: pointer to a object's method (this call)
    typedef DWORD (T::* Method)(void);
// -----------------------------------------------------------------------------
protected:
    HANDLE  hThread;      // unique handle to the thread
private:
    DWORD   threadID;     // thread id - 0 until started
    T*      object;       // the object which owns the method
    Method  method;       // the method of the object
    HANDLE  hInterrupt;   // mutex to signal an interrupt via ReleaseSemaphore()
    HANDLE  hSingleStart; // only one thread allowed to call start() mutex
// -----------------------------------------------------------------------------
private:
    // This function gets executed by a concurrent thread.
    static DWORD run(LPVOID thread_obj)
    {
        Thread<T>* thread = (Thread<T>*)thread_obj;
        return (thread->object->*thread->method) ();
    }
    // Prevent copying of threads: No sensible implementation!
    Thread(const Thread<T>& other) {}
    // Prevent assignment of threads: No sensible implementation!
    Thread<T>& operator =(const Thread<T>& other) {}
// -----------------------------------------------------------------------------
public:
    /* Creates a new Thread object. object: the one which method should be
    executed. method: pointer to the object's method. */
    explicit Thread(T* object, DWORD ( T::* method)(void))
    {
        this->hThread       = NULL;
        this->object        = object;
        this->method        = method;
        this->threadID      = 0;
        this->hInterrupt    = CreateSemaphore(NULL, 1, 1, NULL);
        this->hSingleStart  = CreateMutex(NULL, FALSE, NULL);
        // this->hInterrupt = CreateMutex(NULL, FALSE, NULL);
    }
// -----------------------------------------------------------------------------
    ~Thread(void)
    {
        if (hInterrupt)
            CloseHandle(hInterrupt);
        if (hThread)
            CloseHandle(hThread);
    }
// -----------------------------------------------------------------------------
    /* Starts executing the objects method in a concurrent thread. True if the
    thread was started successfully; otherwise false. */
    bool start()
    {
        __try {
            if (WaitForSingleObject(hSingleStart, 0) != WAIT_OBJECT_0)
                return false;
            if (hThread)    // Thread had been started sometime in the past
            {
                if (WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT)
                {   // if thread's still running deny new start
                    return false;
                }
                CloseHandle(hThread);
            }
            // (Re-)Set not interrupted semaphore state
            WaitForSingleObject(hInterrupt, 0);

            hThread = CreateThread(
                NULL,
                0,
                (LPTHREAD_START_ROUTINE) Thread<T>::run,
                this,
                0,
                &this->threadID
            );
            if (hThread)
                return true;
            return false;
        }
        __finally
        {
            ReleaseMutex(hSingleStart);
        }
    }
// -----------------------------------------------------------------------------
    // Blocks the calling thread until this thread has stopped.
    inline void join()
    {
        WaitForSingleObject(hThread, INFINITE);
    }
// -----------------------------------------------------------------------------
    /* Asks the thread to exit nicely. Thread function must implement checks.
    return value indicates if the interrupt could be placed not if the thread
    reacts on the interrupt. true indicates success, false an error. */
    inline bool interrupt()
    {
        if (hInterrupt)
        {
            return ((ReleaseSemaphore(hInterrupt, 1, NULL) == FALSE) ?
                false : true);
        }
        return false;
    }
// -----------------------------------------------------------------------------
    /* True if an interrupt request was set, otherwise false. */
    inline bool isInterrupted()
    {
        return this->isInterrupted(0);
    }
// -----------------------------------------------------------------------------
    /* True if an interrupt request was set, otherwise false. Waits for millisec
    milliseconds for the interrupt to take place. */
    inline bool isInterrupted(DWORD millisec)
    {
        if (WaitForSingleObject(hInterrupt, millisec) == WAIT_TIMEOUT)
        {
            return false;
        }
        ReleaseSemaphore(hInterrupt, 1, NULL);  // keep interrupted state
        return true;
    }
// -----------------------------------------------------------------------------
    inline bool isRunning()
    {
        DWORD exitCode = 0;
        if (hThread)
            GetExitCodeThread(hThread, &exitCode);
        if (exitCode == STILL_ACTIVE)
            return true;
        return false;
    }
// -----------------------------------------------------------------------------
    // Getter & Setter
// -----------------------------------------------------------------------------
    __declspec(property(get = getThreadHandle)) HANDLE ThreadHandle;
    inline HANDLE getThreadHandle()
    {
        return hThread;
    }
// -----------------------------------------------------------------------------
    __declspec(property(get = getThreadID)) DWORD ThreadID;
    inline DWORD getThreadID()
    {
        return threadID;
    }
// -----------------------------------------------------------------------------
};
// #############################################################################
#endif // __THREAD_H__

Short example:

短的例子:

// main.cpp    
#include <iostream>
#include <string>

#include "Thread.h"

class HelloWorld
{
public:
    DWORD print ()
    {
        std::cout << "Hello World!" << std::endl;
        return 0;
    }
};
int main(void)
{
    // Random object with DWORD method (void)
    HelloWorld world;
    // thread should call print method of world.
    Thread<HelloWorld> thread(&world, &HelloWorld::print);
    if (thread.start())
        std::cout << "Thread start()" << std::endl;
    thread.join(); // wait for thread
    return 0;
}

#1


62  

You need to create a static method to use as the actual thread start function, and pass a pointer to the instance as the lpParameter argument to CreateThread. That will get passed to the static method, which can cast it to an object pointer and call through to the member function.

您需要创建一个静态方法,将其用作实际的线程启动函数,并将指针作为lpParameter参数传递给该实例,以创建CreateThread。它将传递给静态方法,静态方法可以将它转换为对象指针并调用成员函数。

class MyClass
{
    static DWORD WINAPI StaticThreadStart(void* Param)
    {
        MyClass* This = (MyClass*) Param;
        return This->ThreadStart();
    }

    DWORD ThreadStart(void)
    {
        // Do stuff
    }

    void startMyThread()
    {
       DWORD ThreadID;
       CreateThread(NULL, 0, StaticThreadStart, (void*) this, 0, &ThreadID);
    }
};

#2


9  

Others who come across, might want to use my solution. It's a complete Source File compiled with VS2008. See below for a short instruction example on how to use!

其他遇到的人可能想用我的解决方案。它是用VS2008编译的一个完整的源文件。下面是一个关于如何使用的简短说明示例!

// Thread.h
#ifndef __THREAD_H__
#define __THREAD_H__
// #############################################################################
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// =============================================================================
template<class T>
class Thread
{
    // new type Method: pointer to a object's method (this call)
    typedef DWORD (T::* Method)(void);
// -----------------------------------------------------------------------------
protected:
    HANDLE  hThread;      // unique handle to the thread
private:
    DWORD   threadID;     // thread id - 0 until started
    T*      object;       // the object which owns the method
    Method  method;       // the method of the object
    HANDLE  hInterrupt;   // mutex to signal an interrupt via ReleaseSemaphore()
    HANDLE  hSingleStart; // only one thread allowed to call start() mutex
// -----------------------------------------------------------------------------
private:
    // This function gets executed by a concurrent thread.
    static DWORD run(LPVOID thread_obj)
    {
        Thread<T>* thread = (Thread<T>*)thread_obj;
        return (thread->object->*thread->method) ();
    }
    // Prevent copying of threads: No sensible implementation!
    Thread(const Thread<T>& other) {}
    // Prevent assignment of threads: No sensible implementation!
    Thread<T>& operator =(const Thread<T>& other) {}
// -----------------------------------------------------------------------------
public:
    /* Creates a new Thread object. object: the one which method should be
    executed. method: pointer to the object's method. */
    explicit Thread(T* object, DWORD ( T::* method)(void))
    {
        this->hThread       = NULL;
        this->object        = object;
        this->method        = method;
        this->threadID      = 0;
        this->hInterrupt    = CreateSemaphore(NULL, 1, 1, NULL);
        this->hSingleStart  = CreateMutex(NULL, FALSE, NULL);
        // this->hInterrupt = CreateMutex(NULL, FALSE, NULL);
    }
// -----------------------------------------------------------------------------
    ~Thread(void)
    {
        if (hInterrupt)
            CloseHandle(hInterrupt);
        if (hThread)
            CloseHandle(hThread);
    }
// -----------------------------------------------------------------------------
    /* Starts executing the objects method in a concurrent thread. True if the
    thread was started successfully; otherwise false. */
    bool start()
    {
        __try {
            if (WaitForSingleObject(hSingleStart, 0) != WAIT_OBJECT_0)
                return false;
            if (hThread)    // Thread had been started sometime in the past
            {
                if (WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT)
                {   // if thread's still running deny new start
                    return false;
                }
                CloseHandle(hThread);
            }
            // (Re-)Set not interrupted semaphore state
            WaitForSingleObject(hInterrupt, 0);

            hThread = CreateThread(
                NULL,
                0,
                (LPTHREAD_START_ROUTINE) Thread<T>::run,
                this,
                0,
                &this->threadID
            );
            if (hThread)
                return true;
            return false;
        }
        __finally
        {
            ReleaseMutex(hSingleStart);
        }
    }
// -----------------------------------------------------------------------------
    // Blocks the calling thread until this thread has stopped.
    inline void join()
    {
        WaitForSingleObject(hThread, INFINITE);
    }
// -----------------------------------------------------------------------------
    /* Asks the thread to exit nicely. Thread function must implement checks.
    return value indicates if the interrupt could be placed not if the thread
    reacts on the interrupt. true indicates success, false an error. */
    inline bool interrupt()
    {
        if (hInterrupt)
        {
            return ((ReleaseSemaphore(hInterrupt, 1, NULL) == FALSE) ?
                false : true);
        }
        return false;
    }
// -----------------------------------------------------------------------------
    /* True if an interrupt request was set, otherwise false. */
    inline bool isInterrupted()
    {
        return this->isInterrupted(0);
    }
// -----------------------------------------------------------------------------
    /* True if an interrupt request was set, otherwise false. Waits for millisec
    milliseconds for the interrupt to take place. */
    inline bool isInterrupted(DWORD millisec)
    {
        if (WaitForSingleObject(hInterrupt, millisec) == WAIT_TIMEOUT)
        {
            return false;
        }
        ReleaseSemaphore(hInterrupt, 1, NULL);  // keep interrupted state
        return true;
    }
// -----------------------------------------------------------------------------
    inline bool isRunning()
    {
        DWORD exitCode = 0;
        if (hThread)
            GetExitCodeThread(hThread, &exitCode);
        if (exitCode == STILL_ACTIVE)
            return true;
        return false;
    }
// -----------------------------------------------------------------------------
    // Getter & Setter
// -----------------------------------------------------------------------------
    __declspec(property(get = getThreadHandle)) HANDLE ThreadHandle;
    inline HANDLE getThreadHandle()
    {
        return hThread;
    }
// -----------------------------------------------------------------------------
    __declspec(property(get = getThreadID)) DWORD ThreadID;
    inline DWORD getThreadID()
    {
        return threadID;
    }
// -----------------------------------------------------------------------------
};
// #############################################################################
#endif // __THREAD_H__

Short example:

短的例子:

// main.cpp    
#include <iostream>
#include <string>

#include "Thread.h"

class HelloWorld
{
public:
    DWORD print ()
    {
        std::cout << "Hello World!" << std::endl;
        return 0;
    }
};
int main(void)
{
    // Random object with DWORD method (void)
    HelloWorld world;
    // thread should call print method of world.
    Thread<HelloWorld> thread(&world, &HelloWorld::print);
    if (thread.start())
        std::cout << "Thread start()" << std::endl;
    thread.join(); // wait for thread
    return 0;
}