使用多线程处理对象数组 - 无效使用 void 表达式错误



我需要运行一定数量的线程来处理对象数组。

所以我写了这段代码:

unsigned int object_counter = 0;
while(object_counter != (obj_max - left))
{
    thread genThread[thread_num];//create thread objects
    ///launch threads
    int thread_index = 0;
    for (; thread_index<thread_num; thread_index++)
    {
        genThread[thread_index] = thread(object[object_counter].gen_maps());//launch a thread
        object_counter++;
        if(object_counter == (obj_max - left)
        {
            break;
        }
    }
    ///finish threads
    for (; thread_index>0; thread_index--)
    {
        genThread[thread_index].join();
    }
}

基本上,有一个对象数组(对象数量 = obj_max - left )。每个对象都有一个称为 gen_maps() 的函数(空隙类型函数),用于生成地形。

我想做的是使用多线程从所有对象运行所有gen_maps()函数。

最大线程数存储在thread_num变量中。

但是当我尝试编译此代码时,我收到一个错误:

error: invalid use of void expression
         genThread[thread_index] = thread(object[object_counter].gen_maps(), thread_index);//launch a thread
                                                                                         ^

如何解决此问题?

使用较少的线程数管理任意大量作业的更可扩展的方法是使用线程池。

这是一个朴素的实现(为了提高效率,将有 2 个条件变量来管理控制和状态报告),它允许发起方添加任意数量的作业或线程并等待所有作业完成。

#include <thread>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <functional>
#include <deque>
#include <cassert>
#include <ciso646>
#include <iostream>
struct work_pool
{
    std::mutex control_mutex;
    std::condition_variable control_cv;
    std::deque<std::function<void()>> jobs;
    bool terminating = false;
    std::size_t running = 0;
    std::vector<std::thread> threads;
    work_pool(std::size_t n = std::thread::hardware_concurrency())
    {
        add_threads(n);
    }
    work_pool(const work_pool&) = delete;
    work_pool& operator=(const work_pool&) = delete;
    ~work_pool()
    {
        wait();
        shutdown();
    }

    void add_threads(std::size_t n)
    {
        while (n--)
        {
            threads.emplace_back([this]{
                run_jobs();
            });
        }
    }
    void run_jobs()
    {
        while (1)
        {
            auto lock = std::unique_lock(control_mutex);
            control_cv.wait(lock, [this] {
                return terminating or not jobs.empty();
            });
            if (terminating) return;
            ++running;
            auto job = std::move(jobs.front());
            jobs.pop_front();
            lock.unlock();
            job();
            lock.lock();
            --running;
            lock.unlock();
            control_cv.notify_one();
        }
    }
    void shutdown()
    {
        auto lock = std::unique_lock(control_mutex);
        terminating = true;
        lock.unlock();
        control_cv.notify_all();
        for (auto&& t : threads) {
            if (t.joinable()) {
                t.join();
            }
        }
        threads.clear();
    }
    void wait()
    {
        auto lock = std::unique_lock(control_mutex);
        control_cv.wait(lock, [this] {
            return jobs.empty() and not running;
        });
    }
    template<class F>
    void add_work(F&& f)
    {
        auto lock = std::unique_lock(control_mutex);
        assert(not terminating);
        jobs.emplace_back(std::forward<F>(f));
        lock.unlock();
        control_cv.notify_all();
    }
};
// dummy function for exposition
void generate_map() {}
int main()
{
    work_pool pool;
    for(int i = 0 ; i < 100000 ; ++i)
        pool.add_work(generate_map);
    pool.wait();
    // maps are now all generated
    std::cout << "done" << std::endl;   
} 

使用 object[object_counter].gen_maps() 调用函数gen_maps并使用返回的值作为线程函数。显然gen_maps被声明为返回void这会导致您得到的错误。

您需要传递指向函数的指针,然后将应调用的对象作为参数传递给线程:

thread(&SomeClass::gen_maps, object[object_counter])

最新更新