在C++中调度辅助作业并在主线程中接收回调

Scheduling a worker job and receiving a callback in the main thread in C++

本文关键字:线程 回调 作业 C++ 调度      更新时间:2023-10-16

在我当前的代码中,我有一个解决方案,允许主线程调度一些作业在工作线程中异步执行。

当工作线程完成时,它应该使用提供的回调函数通知主线程。主要的问题是,我希望这个回调在主线程中执行,而不是在工作线程中执行。因此,在工作线程完成任务后,从工作线程进行简单的函数调用是不可行的(回调执行的一些应用程序逻辑可能相当复杂,我不希望工作线程忙于此)。

我有一个解决这个问题的遗留解决方案(使用事件向主线程发出作业已完成的信号等),但我正在寻找一些通用且可重复使用的解决方案——C++中有什么我可以使用的吗?

理想情况下,我正在寻找像boost::signals这样的解决方案,但据我所知,这不是线程感知的。有什么想法吗?

EDIT:最终解决方案必须在linux上运行,并使用GCC 进行编译

EDIT2:添加的一些示例代码

回调的典型用法可能是这样的(这不会编译,但我想保持简单,以显示总体想法):

///////// main thread ////////////
void fun() { /* work to be done in worker thread */ }
void callback() { /* callback that will be called when fun() is done */ }
int main() {
    Worker worker;
    worker.doAsync(fun, callback);
    // waiting for the worker to finish the job
}
////// worker thread code ///////
/// main worker loop
void Worker::run() {
    // wait until the task is scheduled 
    // run the scheduled tasks
    fun();
    // when task was finished, call the callback
    callback();
}

上面代码的问题是callback()函数将从工作线程调用——我想要的是让工作线程向主线程发出作业已完成的信号,而主线程现在应该调用回调,因为作业已完成。

如果您可以使用C++11,您可能会看到std::future类。无论如何,您需要以某种方式等待主线程中的事件。

std::future<T> f = std::async(std::launch::async, <your_thread_func>);
// do something else
f.wait();
T t = f.get();

如果您的工作线程要返回一个值,请使用future,否则,您可以生成工作线程,并告诉主线程等待它们在threadxxx.join()之前完成。这里有两个例子:

带有thread s:

#include <thread>
int main()
{
    std::thread thread1(fun);
    //anything here will be run simultaneously
    ...
    thread1.join();
    //anything here will be run after thread1 is done
    return 0;
}

未来:

#include <future>
#include <thread>
int main()
{
    std::future<double> future1 = std::async(std::launch::async, fun());
    //anything here will run simultaneously;
    ...
    //get() will wait for the result, if the thread is not done yet.
    double res = future1.get();
    //from here on, the task is done
    return 0;
}

您可以使用回调作为mainThreadCallback 的包装器

创建mainThreadCallback

gboolean mainThreadCallback(gpointer data)
{
    //cast data to whatever you need
    return FALSE; // so it will run only once
}

内部

void callback()
{
   g_idle_add ((GSourceFunc) mainThreadCallback, NULL /* custom data */);
}

一旦函数mainThreadCallback可用,它就会在主线程中运行。您需要在int main()函数中有一个GMainLoop。