2017-07-26 538 views
1

我有一个要求在std :: thread退出时执行回调函数,并且回调函数应该在主线程上执行。std :: thread在主线程上执行回调函数

在创建线程时,我需要分离线程并且不能阻塞线程完成的主循环执行。

我试图使用的std ::信号,但是这似乎并没有主线程

#include <thread> 
#include <csignal> 
#include <iostream> 


std::thread::id main_thread_id; 

void func2() 
{ 
    for(int i = 0; i < 10000000; i++) 
    { 
     // do something 
    } 
} 

void func() 
{ 
    for(int i = 0; i < 10; i++) 
    { 
     func2(); 
    } 
    std::raise(SIGUSR1); 
} 

void callback(int signal) 
{ 
    std::cout << "SIGNAL: " << signal << "  THREAD ID:" << 
    std::this_thread::get_id() << std::endl; 
    bool b = std::this_thread::get_id() == main_thread_id; 
    std::cout << "IS EXECUTED ON MAIN THREAD: " << b << std::endl; 
} 

int main() 
{ 
    main_thread_id = std::this_thread::get_id(); 
    std::cout << "MAIN THREAD ID: " << std::this_thread::get_id() << std::endl; 
    std::signal(SIGUSR1, callback); 
    std::thread t1(func); 
    t1.detach(); 

    for(int i = 0; i < 20; i++) 
    { 
     func2(); 
    } 

    if(t1.joinable()) 
     t1.join(); 
} 

结果我得到的是回调函数未在主线程执行上执行回调函数。请建议一种方法,我可以在线程退出时创建工作线程并在主线程上调用回调函数。

感谢您的帮助

+0

检查'std :: signal(SIGUSR1,callback);'返回的值。在某些实现中可以禁用设置信号处理程序。在这种情况下,你将得到'SIG_ERR'(-1) – ikleschenkov

+0

你不能只是停止一个线程(主线程或其他线程)死在它的轨道上,让它执行一些代码,然后恢复它,就像什么都没有发生。线程必须以检查要做的工作的方式编写,然后才能工作。例如,它可能是[生产者 - 消费者]中的消费者(https://www.cs.cornell.edu/courses/cs3110/2010fa/lectures/lec18.html)安排。 –

回答

4

有几种方法可以做到这一点。

首先,您的主线程可能正在运行消息循环。在这种情况下,你用一个有效负载排队消息,告诉主线程运行一些代码(或者将代码通过消息的指针部分运行到主线程,或者将它放在一些已知的主线程检查)。

第二种方法是返回类似于std::future<std::function<void()>>对象的东西,并且主线程检查未来是否准备就绪。准备就绪后,它会运行代码。

第三种方法是创建主线程等待的并发队列,并将消息(包含要运行的代码)填充到该队列中。

所有这些事情都需要主线程的积极配合。主线程不能被抢占,并被要求在没有合作的情况下运行不同的代码。

哪一个最好取决于你没有选择在你的问题中提及的程序的功能。如果您是一个带有消息循环的图形化GUI,请使用消息循环。如果你是一个流处理器,将某些工作同步化,并且不需要及时执行,但最终会阻止并行工作,未来可能是最好的。如果你是一个消息传递通道类型的应用程序,一组队列可能是最好的。