如果线程对象声明为成员,则 Boost 线程启动失败

Boost Thread start failure if thread object declared as member

我写了一个名为 class 的任务,它封装了一个 boost::thread 并允许覆盖 运行() 方法以在新创建的线程上做一些工作。

这里是基础class:

class Task {


    typedef boost::function<void ()> TaskEventCallback;
    typedef boost::unordered_map<string, TaskEventCallback> Callbacks;
    typedef boost::unordered_map<string, Callbacks> SessionTaskMap;
    typedef boost::unordered_map<TaskListener *, SessionTaskMap> ListenersMap;

    public:
        Task(NGSAppServer& server);
        Task(const Task& orig);
        virtual ~Task();

        virtual void run() = 0;
        bool start();
        bool pause();
        bool cancel();

        virtual bool registerListener(TaskListener *);
        virtual bool unregisterListener(TaskListener *);
        string getProgress();
        string getStatusMessage();

        boost::thread * getThread();

    protected:
        void postEvent(string event);
        void startThread();

        void setProgress(string progress);
        void setStatusMessage(string statusMessage);


        vector<TaskListener *> listeners;
        bool taskRunning;
        bool taskStarted;
        bool taskCanceled;
        bool taskEnded;
        NGSAppServer& server;

        boost::thread worker;
        boost::recursive_mutex mutex;

        ListenersMap listeners_map;

    private:
        string progress;
        string statusMessage;

};

class 能够通过服务器 class 将事件 post 发送到多个 http 会话,但这与此处无关。 一切正常,线程启动并且 post 成功事件,直到工作结束。 这是一个工作片段:

        RestoreTask * task = new RestoreTask(application->getServer());
        TaskListener * listener = new TmpTL(*task, progressText, this);
        task->start();

这是还原 class:

        class Restore : public Task {

        public:
            Restore(NGSAppServer& server);
            Restore(const Restore& orig);
            virtual ~Restore();

            virtual void run();

        private:
            ... stuffs ...
        };

现在我尝试将 Restore 任务的工作拆分为 N 个子任务(Worker,也是 Task 的子class)。 这里是 Restore 的新 运行 方法:

            std::vector<Worker *> workers;
            for(uint i = 0; i < 2; i++){
                //Start tread
                Worker _worker(this, server);
                _worker.start();
                workers.push_back(&_worker);
            }

            //Join Workers
            for(uint i = 0; i < 2; i++){
                workers.at(i)->getThread()->join();
            }

此代码失败,因为子线程的启动在尝试 运行 Worker class 运行 方法时创建了一个 sigfault,因为它被报告为纯虚拟,而且尝试锁定任务基础上的互斥量 class 在此断言上失败:

void boost::recursive_mutex::lock(): Assertion `!pthread_mutex_lock(&m)' failed.

直接创建一个 Worker 对象并启动它(对于 Restore)不会产生任何问题!

乍一看,Restore 运行() 方法似乎在子线程之前结束,删除了 Worker 实例,然后在 运行 基础 class 上进行调用(纯虚拟)并尝试访问已损坏的互斥体。 (如果我在这里错了,请纠正我!)

使用调试器深入研究问题我发现情况并非如此。 问题似乎存在于 Worker 对象声明中,因为以下更改使代码可以正常工作:

            std::vector<Worker *> workers;
            for(uint i = 0; i < 2; i++){
                //Start tread
                Worker * _worker = new Worker(this, server);
                _worker->start();
                workers.push_back(_worker);
            }

            for(uint i = 0; i < 2; i++){
                workers.at(i)->getThread()->join();
                delete workers.at(i);
            }

我更愿意在没有 new 运算符的情况下创建 Workers,因为我真的不需要在 Restore::run() 完成后让这些对象保持活动状态,而且我应该能够保证这些对象仍然存在直到子线程由于线程连接而完成(已通过调试器验证)。

谁能找到这里的瓶颈?

我已经能够找到一种方法 运行 我的代码,解决方案(但对我来说更重要的是这里的解释)仍然缺失。

此致

重复for循环时,_worker将超出范围并被销毁。 你可以在析构函数中打印一个来验证这一点。

你在第二个(新的..delete)中所做的是正确的, 也许您可以使用 smart_ptr / make_ptr 来避免删除。

你也可以创建一个 Workers 数组来代替 for-loop, 在这种情况下,您将不得不使用默认构造函数,并以其他方式传递初始值设定项(this,start)