如何在C ++中使函数异步?

时间:2011-04-13 06:42:26

标签: c++ asynchronous

我想调用一个异步的函数(我将在完成此任务时给出回调)。

我想在单线程中执行此操作。

7 个答案:

答案 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 - 例如,当您执行回调时SleepExWaitForSingleObjectEx

答案 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循环很容易-只需创建一个期货数组即可。