如何在c++中创建异步函数
How do I make a function asynchronous in C++?
我想调用一个异步函数(当这个任务完成时我将给出一个回调)。
这可以用现代c++移植,甚至用旧的c++和一些boost来移植。boost和c++ 11都包含从线程获取异步值的复杂工具,但是如果你想要的只是回调,只需启动一个线程并调用它。
1998 c++/boost方法:
#include <iostream>
#include <string>
#include <boost/thread.hpp>
void callback(const std::string& data)
{
std::cout << "Callback called because: " << data << 'n';
}
void task(int time)
{
boost::this_thread::sleep(boost::posix_time::seconds(time));
callback("async task done");
}
int main()
{
boost::thread bt(task, 1);
std::cout << "async task launchedn";
boost::this_thread::sleep(boost::posix_time::seconds(5));
std::cout << "main donen";
bt.join();
}
2011 c++方法(使用gcc 4.5.2,需要这个#define)
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream>
#include <string>
#include <thread>
void callback(const std::string& data)
{
std::cout << "Callback called because: " << data << 'n';
}
void task(int time)
{
std::this_thread::sleep_for(std::chrono::seconds(time));
callback("async task done");
}
int main()
{
std::thread bt(task, 1);
std::cout << "async task launchedn";
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "main donen";
bt.join();
}
从c++ 11开始,普通c++ 确实有线程的概念,但是异步调用函数最简洁的方法是使用c++ 11 async命令和future。这最终看起来很像你在pthreads中做同样事情的方式,但它100%可移植到所有操作系统和平台:
假设你的函数有一个返回值…int = MyFunc(int x, int y)
#include <future>
只做:
// This function is called asynchronously
std::future<int> EventualValue = std::async(std::launch::async, MyFunc, x, y);
抓住吗?你怎么知道什么时候完成?(障碍)。
最终做的事:
int MyReturnValue = EventualValue.get(); // block until MyFunc is done
注意,以这种方式创建并行for循环很容易——只需创建一个期货数组。
在普通c++中不能。您需要使用特定于操作系统的机制,并且需要一个暂停执行的点,以允许操作系统执行回调。例如,对于Windows, QueueUserAPC
-回调将被执行时,例如SleepEx
或WaitForSingleObjectEx
较长的答案包括实现您自己的任务调度程序,并将您的"功能"包装成一个或多个任务。我不确定你是否想要冗长的答案。它当然不允许你调用某个东西,完全忘记它,然后在它完成时得到通知;然而,如果你有雄心壮志,它将允许你在某种程度上模拟协同程序,而无需超出标准c++。
简短的回答是这是不可能的。使用多个线程或多个进程。
要做到这一点需要两个步骤。
首先,将函数调用打包,以便稍后执行。
第二,调度。
调度取决于实现的其他方面。如果你知道"这个任务什么时候完成",那么你所需要的就是返回并检索"函数调用"并调用它。所以我不确定这一定是个大问题。
第一部分实际上是关于函数对象,甚至函数指针。后者是c的传统回调机制。
对于FO,您可能有:
class Callback
{
public:
virtual void callMe() = 0;
};
你从这个推导出来,并按照你认为适合你的具体问题的方式实现它。那么异步事件队列只不过是回调的list<>
:
std::list<Callback*> asyncQ; // Or shared_ptr or whatever.
我不确定我理解你想要什么,但如果它是如何利用回调:它通过定义一个函数指针来工作,像这样(未经测试):
// Define callback signature.
typedef void (*DoneCallback) (int reason, char *explanation);
// A method that takes a callback as argument.
void doSomeWorkWithCallback(DoneCallback done)
{
...
if (done) {
done(1, "Finished");
}
}
//////
// A callback
void myCallback(int reason, char *explanation)
{
printf("Callback called with reason %d: %s", reason, explanation);
}
/////
// Put them together
doSomeWortkWithCallback(myCallback);
正如其他人所说,从技术上讲,在普通的c++中不能这样做。
然而,你可以创建一个管理器来处理你的任务,并进行时间切片或时间调度;对于每个函数调用,管理器使用计时器来测量该过程所花费的时间;如果进程花费的时间少于预定的时间,并且它认为它可以完成另一个调用,并且用完剩余的时间而不会超时,它可以再次调用它;如果函数确实超过了分配的时间,这意味着函数下一次更新运行的时间更少。因此,这将涉及创建一个稍微复杂的系统来为您处理它。
或者,如果您心中有一个特定的平台,您可以使用线程,或者创建另一个进程来处理工作。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建 Spdlog 异步文件记录器时遇到困难
- 调用boost.asio的异步函数时,线程是什么时候创建的
- STD :: async的最大线程数量是多少,将异步创建和执行
- 异步服务器在创建boost :: asio后立即关闭
- C++ 异步创建对象
- 进行异步调用 - 我必须创建自己的p/s吗?
- QT-如何异步创建小部件
- 如何在C++中创建异步/等待代码
- hiredis Redis 库是否为异步回调创建了自己的线程
- Visual C++/CLI 中的异步睡眠,如何创建一个 X 毫秒来调用函数,而不会使 GUI 也停止
- 如何创建异步函数
- 我可以在 boost::asio 异步模式下创建和接受套接字时使用 boost::shared_ptr 吗?
- GameMaker Studio,从Windows DLL创建异步事件
- 如何在c++中创建异步函数