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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5645375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:35:28  来源:igfitidea点击:

How do I make a function asynchronous in C++?

c++asynchronous

提问by yogesh

I want to call a function which will be asynchronous (I will give a callback when this task is done).

我想调用一个异步函数(当这个任务完成时我会给出一个回调)。

I want to do this in single thread.

我想在单线程中做到这一点。

回答by Cubbi

This can be done portably with modern C++ or even with old C++ and some boost. Both boost and C++11 include sophisticated facilities to obtain asynchronous values from threads, but if all you want is a callback, just launch a thread and call it.

这可以通过现代 C++ 甚至旧 C++ 和一些boost轻松完成。boost 和 C++11 都包含从线程获取异步值的复杂工具,但如果您想要的只是回调,只需启动一个线程并调用它即可。

1998 C++/boost approach:

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++ approach (using gcc 4.5.2, which needs this #define)

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();
}

回答by Erik

You can't in plain C++. You'll need to use an OS-specific mechanism, and you need a point where execution is suspended in a way that allows the OS to execute the callback. E.g. for Windows, QueueUserAPC- the callback will be executed when you e.g. SleepExor WaitForSingleObjectEx

你不能在普通的 C++ 中。您将需要使用特定于操作系统的机制,并且您需要一个暂停执行的点,以允许操作系统执行回调。例如,对于 Windows,QueueUserAPC- 当您例如SleepExWaitForSingleObjectEx

回答by Ken Rockot

The long answer involves implementing your own task scheduler and wrapping your "function" up into one or more tasks. I'm not sure you want the long answer. It certainly doesn't allow you to call something, completely forget about it, and then be notified when that thing is done; however if you are feeling ambitious, it will allow you to simulate coroutines on some level without reaching outside of standard C++.

长答案涉及实现您自己的任务调度程序并将您的“功能”包装成一个或多个任务。我不确定你想要长长的答案。它当然不允许你打电话,完全忘记它,然后当那件事完成时得到通知;但是,如果您有雄心壮志,它将允许您在某种程度上模拟协程,而无需超出标准 C++。

The short answer is that this isn't possible. Use multiple threads or multiple processes. I can give you more specific information if you divulge what OS/platform you're developing for.

简短的回答是,这是不可能的。使用多线程或多进程。如果您透露您正在开发的操作系统/平台,我可以为您提供更具体的信息。

回答by Keith

There are two bits to doing this.

这样做有两点。

Firstly, packing up the function call so that it can be executed later.

首先,打包函数调用,以便稍后执行。

Secondly, scheduling it.

其次,调度。

It is the scheduling which depends on other aspects of the implementation. If you know "when this task is done", then that's all you need - to go back and retrieve the "function call" and call it. So I am not sure this is necessarily a big problem.

调度取决于实现的其他方面。如果您知道“当此任务完成时”,那么这就是您所需要的 - 返回并检索“函数调用”并调用它。所以我不确定这一定是一个大问题。

The first part is then really about function objects, or even function pointers. The latter are the traditional callback mechanism from C.

第一部分实际上是关于函数对象,甚至是函数指针。后者是来自 C 的传统回调机制。

For a FO, you might have:

对于 FO,您可能有:

class Callback
{
public:
  virtual void callMe() = 0;
};

You derive from this and implement that as you see fit for your specific problem. The asyncronous event queue is then nothing more than a list<>of callbacks:

您从中得出并实施您认为适合您的特定问题的方法。异步事件队列不过是一个list<>回调:

std::list<Callback*> asyncQ; // Or shared_ptr or whatever.

回答by DarkDust

I'm not sure I understand what you want, but if it's how to make use of a callback: It works by defining a function pointer, like this (untested):

我不确定我是否理解你想要什么,但如果它是如何使用回调:它通过定义一个函数指针来工作,像这样(未经测试):

// 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);

回答by leetNightshade

As others have said, you technically can't in plain C++.

正如其他人所说,从技术上讲,您不能使用纯 C++。

However, you can create a manager that takes your task and does time-slicing or time scheduling; with each function call, the manager uses a timer to measure the amount of time the process took; if the process took less time than scheduled, and it thinks it can finish another call and use up the remaining time without going over, it can call it again; if the function does go over the alloted time, it means the function has less time next update to run. So, this will involve creating a somewhat complex system to handle it for you.

但是,您可以创建一个管理器来处理您的任务并进行时间切片或时间安排;对于每个函数调用,管理器使用一个计时器来测量进程花费的时间;如果进程花费的时间少于预定的时间,并且它认为它可以完成另一个调用并用完剩余的时间而不继续,它可以再次调用它;如果函数确实超过了分配的时间,则意味着该函数下次更新运行的时间更少。因此,这将涉及创建一个稍微复杂的系统来为您处理它。

Or, if you have a specific platform in mind, you could use threading, or create another process to handle the work.

或者,如果您有一个特定的平台,您可以使用线程,或创建另一个进程来处理工作。

回答by user2465201

As of C++11, plain c++ doeshave a concept of threads, but the most concise way to call a function asynchronously is to use the C++11 async command along with futures. This ends up looking a lot like the way you'd do the same thing in pthreads, but it's 100% portable to all OSes and platforms:

从 C++11 开始,普通 C++确实有线程的概念,但异步调用函数的最简洁方法是将 C++11 异步命令与期货一起使用。这最终看起来很像你在 pthreads 中做同样事情的方式,但它 100% 可移植到所有操作系统和平台:

Say your function has a return value... int = MyFunc(int x, int y)

假设你的函数有一个返回值... int = MyFunc(int x, int y)

#include <future>

Just do:

做就是了:

// This function is called asynchronously
std::future<int> EventualValue = std::async(std::launch::async, MyFunc, x, y); 

Catch? How do you know when it's done? (The barrier.)

抓住?你怎么知道什么时候完成?(屏障。)

Eventually, do:

最后,做:

int MyReturnValue = EventualValue.get(); // block until MyFunc is done

Note it's easy to do a parallel for loop this way - just create an array of futures.

请注意,以这种方式执行并行 for 循环很容易 - 只需创建一个期货数组。