基于C++模板,可以实现三种异步发送和接收数据的方法。std::future和std::promise结合可以实现异步功能场景。本文介绍的异步收发数据模板类在实践中结合std::future和std::promise。在工作过程中,我们可能经常会遇到这样的场景,需要从线程中获取运行结果。现在我们有两种方法来实现这个效果。第一种方式,属于普通用法,线程之间通过指针共享数据。将指针传递给新创建的线程,主线程使用条件变量等待被唤醒;当线程将数据设置到传递的指针时,它发送一个条件变量信号,主线程唤醒后,它从指针中提取数据。这种方法使用条件变量、锁和指针的组合来实现异步功能,比较复杂。第二种方法使用std::future和std::promise对象,这是一种异步的实现方式,本文将详细介绍。std::future是一个类模板,在内部存储一个值以供将来分配,它提供了一个get()成员函数来访问值机制。如果在关联值可用之前调用get函数,则get函数将阻塞,直到关联值不可用。std::promise也是一个类模板,用于设置上面的关联值,每个stb::promise关联一个std::future对象,一旦stb::promise的值被设置,get()函数将获取值并返回。std::promise与其关联的std::future共享数据。一、阻塞等待获取数据1、实现线程执行函数,入参为一个std::promise指针,在函数中调用std::promise指针设置值2、定义std::promise对象,并从object::future对象中获取关联的std,启动线程并传入std::promise对象的指针,调用std::future对象的get()函数阻塞等待,如果是returns,打印出返回的字符串信息。3、运行程序,输出信息如下。由此可见,std::promise在线程中设置值后,std::future对象的get()函数成功获取并返回。2.通知线程退出基于std::promise和std::future的机制,我们可以通过std::promise的set_value来通知正在运行的线程退出。具体怎么做,我们会举个例子来说明。1、实现线程的执行函数。输入参数是与std::promise关联的std::future对象。执行函数内部调用std::future的wait_for循环等待超时。如果std::future的wait_for在超时时间内没有过期收到std::promise发送的信号调用set_value,则继续循环等待,如果在超时时间内收到std::promise发送的信号调用set_valueperiod,然后退出循环,线程也退出。2、创建一个std::promise对象,从std::promise对象中提取出关联的future对象,启动线程,将上面的future对象传递给线程。主线程休眠一段时间后,调用std::promise对象的set_value函数发送信号,通知线程退出3.从输出结果信息来看,线程一直在运行,收到后退出std::promise对象发送的信号3.异步收发数据经过上面两个例子的讲解,相信大家已经对std::future和std::promise有了一个大概的了解。下面给出异步发送和接收数据的模板类。1、类模板JAsyncSender实现了两个功能,一个是发送数据的Send,可以在一个线程中执行,一个是Wait接收数据。如果不输入第三个参数,则默认等待,否则在指定时间等待2、接下来讲解类模板JAsyncSender的使用方法。定义成员变量m_AsyncSendInt,主线程和子线程共享。JAsyncSender的类型是整数,也可以定义为字符串,甚至是自定义对象,根据具体的需求场景来定义。通过lambda创建线程。当然,您也可以使用其他方法。线程在发送数据前会休眠一段时间。从运行结果来看,基于future和promise实现的异步收发数据模板类功能正常。4.小结std::promise和std::future的结合可以更容易的处理异步消息事件。另外,C++11标准中提供的std::asych和std::packaged_task也是结合std::future异步事件流处理的。虽然std::promise和std::future很强大,但是std::promise和std::future是一一对应的。目前,没有办法处理一对多的问题。例如,一个std::promise对应多个std::future。如果设置过一次std::promise,再次设置会报错。如果需要重用,需要重新创建一个std::promise对象。
