2

在尝试实现异步 API 调用/非阻塞调用时,我在我拥有的 All Plain-C 应用程序中了解一点,我读了一篇关于“代表”的 APM(异步编程模型)的文章。基本上我想做的是调用一个 APIf1()来做一个功能(这需要很长时间 8-10 秒),所以我调用那个 API f1(),忘记它,并继续做一些其他的工作,例如 I/O 来获取数据对于f1()不依赖于结果的 或某些功能的下一次调用f1()

如果有人使用过 APM 编程模型,我正在寻找一些关于实现非阻塞调用的简明解释。

是否有任何其他方式来实现异步 API,任何其他可能对此有所帮助的库/框架?

4

5 回答 5

1

您基本上需要创建一个多线程(或多进程)应用程序。f1() API 需要产生一个线程(或进程)以在单独的执行空间中处理数据。当它完成时,f1() 例程需要向主进程发出执行完成的信号(signal()、消息队列等)。

于 2008-09-15T13:25:28.953 回答
1

在纯 C 程序中进行异步编程的一种流行方法是使用“事件循环”。您可以使用许多库。我建议看看 glib

另一种选择是使用多个抢先线程(每个并发操作一个)并将它们与互斥锁和条件变量同步。但是,我会避免使用纯 C 语言中的抢占式线程,尤其是在您想编写可移植程序时。很难知道哪些库函数是可重入的,线程程序中的信号处理很麻烦,而且通常 C 库和系统函数都是为单线程使用而设计的。

如果您计划仅在一个平台(如 Windows)上运行您的应用程序,并且使用 f1() 完成的工作相对简单,那么线程就可以了。

于 2008-09-15T14:08:33.687 回答
1

如果您所指的函数 f1() 本身没有以异步方式实现,则您需要自己将其包装在自己的线程中。执行此操作时,您需要注意可能由调用的特定函数引起的副作用。许多库不是以线程安全的方式设计的,从这些库中多次并发调用函数会导致数据损坏。在这种情况下,您可能需要将功能封装在外部工作进程中。对于您提到的繁重工作(8-10 秒),开销可能是可以接受的。如果您一次只在一个线程中使用外部非线程安全函数,那么您可能是安全的。

使用任何形式的事件循环的问题在于,不知道您的循环的外部函数永远不会将控制权交还给您的循环。因此,您将不会做任何其他事情。

于 2008-09-30T11:47:56.843 回答
0

用指向 C 中函数的指针替换委托,其他一切都与您阅读的内容基本相同。

于 2008-09-15T12:33:36.100 回答
0

出色地。基本上我见过 2 种类型的异步 API:

  1. 打断。您给呼叫一个回调,该回调应在呼叫之后执行。GIO(前面提到的 GLib 的一部分)以这种方式工作。它相对容易编程,但您通常会更改运行回调的线程(除非它与 GIO 的情况下的主循环集成)。
  2. 轮询。您检查数据是否可用。众所周知的 BSD 套接字以这种方式运行。它的优点是不必与主循环集成并在特定线程中运行回调。

如果您为 Gnome 或基于 Gtk+ 的程序编程,我想补充一点,GTask似乎非常好(可能很好?我没用过)。Vala将对类似 GIO 的异步调用提供更好的支持。

于 2009-04-19T09:24:51.037 回答