【问题标题】:Scheduling a worker job and receiving a callback in the main thread in C++在 C++ 中的主线程中调度工作任务并接收回调
【发布时间】:2015-02-20 12:35:54
【问题描述】:

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

当工作线程完成时,它应该使用提供的回调函数通知主线程。主要问题是我希望这个回调在主线程而不是工作线程中执行,所以在工作完成后从工作线程调用简单的函数不是一个选项(回调执行一些可能非常复杂的应用程序逻辑,并且我不希望工作线程忙于那个)。

我有一个针对该问题的旧式解决方案(使用事件向主线程发出工作已完成的信号等),但我正在寻找一些通用且可重用的解决方案 - C++ 中有什么可以使用的吗?

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

编辑:最终解决方案必须在 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();
}

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

【问题讨论】:

  • 我认为您尝试完成的一些代码示例将有助于澄清。
  • boost::signals 已被弃用,取而代之的是线程安全的 boost::signals2。
  • 您为什么将事件描述为遗留解决方案?
  • Oktalist,我的意思是我们的项目中有一些遗留代码正在解决这个问题(使用基于事件的系统,但这并不相关)。所有代码都是自定义解决方案。我有一种感觉,一定有某种标准工具可以在这里应用,而不是从头开始构建所有东西。

标签: c++ multithreading boost


【解决方案1】:

如果你会使用 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();

【讨论】:

    【解决方案2】:

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

    threads:

    #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;
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用回调作为 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。

      【讨论】:

        猜你喜欢
        • 2013-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多