我想调用一个异步的函数(我将在完成此任务时给出回调)。
我想在单线程中执行此操作。
答案 0 :(得分:15)
这可以通过现代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 launched\n";
boost::this_thread::sleep(boost::posix_time::seconds(5));
std::cout << "main done\n";
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 launched\n";
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "main done\n";
bt.join();
}
答案 1 :(得分:5)
你不能用普通的C ++。您需要使用特定于操作系统的机制,并且需要以允许操作系统执行回调的方式暂停执行的点。例如。对于Windows,QueueUserAPC
- 例如,当您执行回调时SleepEx
或WaitForSingleObjectEx
答案 2 :(得分:3)
长答案涉及实施您自己的任务计划程序并将您的“功能”包装成一个或多个任务。我不确定你想要答案很长。它当然不允许你调用某些东西,完全忘记它,然后在完成该事情时得到通知;但是如果你感觉雄心勃勃,它将允许你在某种程度上模拟协程,而不会超出标准C ++。
简短的回答是,这是不可能的。使用多个线程或多个进程。如果您透露正在开发的操作系统/平台,我可以为您提供更具体的信息。
答案 3 :(得分:3)
这样做有两个位。
首先,打包函数调用,以便以后执行。
其次,安排它。
这是依赖于实现的其他方面的调度。如果你知道&#34;当这项任务完成后,那就是你需要的全部内容 - 返回并检索&#34;函数调用&#34;并称之为。所以我不确定这是一个大问题。
第一部分实际上是关于函数对象,甚至是函数指针。后者是C的传统回调机制。
对于FO,您可能有:
class Callback
{
public:
virtual void callMe() = 0;
};
您可以从中获得并实现您认为适合您的特定问题。异步事件队列只不过是list<>
个回调:
std::list<Callback*> asyncQ; // Or shared_ptr or whatever.
答案 4 :(得分:1)
我不确定我理解你想要什么,但是如果它是如何使用回调:它通过定义一个函数指针来工作,就像这样(未经测试):
// 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);
答案 5 :(得分:0)
正如其他人所说,你在技术上不能用普通的C ++。
但是,您可以创建一个管理器来完成任务并进行时间切片或时间安排;对于每个函数调用,管理器使用计时器来测量进程所花费的时间;如果这个过程花费的时间少于预定的时间,并且它认为它可以完成另一个呼叫并且用完剩余的时间而不会过去,它可以再次呼叫它;如果函数确实超过了分配的时间,则意味着该函数在下次更新运行时的时间更短。因此,这将涉及创建一个有点复杂的系统来为您处理它。
或者,如果您有一个特定的平台,您可以使用线程,或创建另一个流程来处理工作。
答案 6 :(得分:0)
从C ++ 11开始,普通的c ++ 确实具有线程的概念,但是异步调用函数的最简洁的方法是将C ++ 11异步命令与Future一起使用。最终看起来很像您在pthread中执行相同操作的方式,但是100%可移植到所有OS和平台上:
说您的函数有一个返回值... 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循环很容易-只需创建一个期货数组即可。