【问题标题】:How to start a new thread for a procedure for a member object如何为成员对象的过程启动新线程
【发布时间】:2015-02-18 09:09:48
【问题描述】:

我正在尝试从我的 main() 开始一个方法,作为一个带有 pthread 的新线程:

int main(int argc, char** argv) {
    pthread_t shipGeneratorThread;
    Port portMelbourne;

    pthread_create(&shipGeneratorThread, NULL, portMelbourne.generateShips(), NULL);

    return (EXIT_SUCCESS);
}

Port 类有一个生成船的函数:

void Port::generateShips() {
    //Generate 1 cargo ship every 2.5 hours
    bool stop = false;

    while(!stop) {
        if(numberOfShipsInBay < 20) {
            Ship ship;
            ship.setTicket(numberOfShipsInBay);
            shipsWaitingToDock[numberOfShipsInBay] = ship;
            term.displayMessage("A new ship has entered the port");
            numberOfShipsInBay++;
        } else {
            term.displayMessage("A ship has been sent to another port");
        }
        usleep(FIVE_MINUTES * 30); //2.5 hours simulated time
    }
}

但是编译器给了我一个错误,“无效使用无效表达式”用于 pthread 创建函数。

我是 C++ 和线程的新手,有什么想法吗?

【问题讨论】:

标签: c++ multithreading object pthreads


【解决方案1】:

在这种情况下您应该使用静态方法,是的,请查看 man pthread_create。 函数的签名很重要。

此外,如果您创建线程方式,您的代码将在 main() 退出后立即终止。 您需要等待线程完成。我在下面举个例子。它并不理想,但似乎足以用于演示。

在处理线程启动时,请注意静态 -> 非静态方法转换。这是常见的方法(尽管不是唯一可能的方法)。

#include <stdio.h>
#include <pthread.h>

class Test {
    public:
        static void* Run(void* me) {
            static_cast<Test*>(me)->RunMe();
            return NULL;
        }

    private:
        void RunMe() {
            printf("%p: %p is running.\n", pthread_self(), this);
        }
};

int main() {

    pthread_t tid;
    Test test;

    printf("%p: creating thread for %p is running.\n", pthread_self(), &test);
    pthread_create(&tid, NULL, Test::Run, &test);
    printf("%p: waiting %p to finish.\n", pthread_self(), &test);

    // In real code you should check 'create' operation result.
    pthread_join(tid, NULL);
    printf("%p: OK, exiting\n", pthread_self());

    return 0;
}

【讨论】:

    【解决方案2】:

    你需要 "static void* generateShips(void*)" 并使用 "pthread_create(&shipGeneratorThread, NULL, Port::generateShips, NULL); ”。

    问候。

    【讨论】:

    • 如果您需要一个 Port 实例,请将 Port 实例作为参数发送,然后在 generateShips 方法中执行从 void* 到 Port* 的转换。 Salu2.
    • 我认为你需要在Port::generateShips之后去掉括号。
    【解决方案3】:
    /* you need a wrapper function like this, it can be also a static method of some class */
    void *GenerateShipsThread(void *port)
    {
        /* do desired action */
        reinterpret_cast<Port*>(port)->generateShips();
    
        /* destroy Port object here or somewhere else */
        delete reinterpret_cast<Port*>(port);
    
        return NULL;
    }
    
    int main(int argc, char** argv) {
        pthread_t shipGeneratorThread;
    
        /* Port object is passed to the thread so you don't want it to be
         * destoyed when this function returns - create it on the heap */
        Port *portMelbourne = new Port();
    
        pthread_create(&shipGeneratorThread, NULL, GenerateShipsWrapper, portMelbourne);
    
        return (EXIT_SUCCESS);
    }
    

    【讨论】:

    • 这根本行不通,因为程序甚至可以在线程主体开始之前终止;)。
    • 我不是在解决这个问题,我是在回答这个问题。无论如何,作者给出了最小的例子,可能在实际代码中main不会在启动线程后立即退出,这毫无意义。
    • 不考虑你的想法,我们也可以说“嘿,这行不通,你不是 Port 类!”
    猜你喜欢
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2021-09-25
    相关资源
    最近更新 更多