异步API

时间:2020-03-05 18:53:18  来源:igfitidea点击:

在尝试实现异步API调用/非阻塞调用时,我在我拥有的All Plain-C应用程序中了解了一点,我读了一篇有关"代表"的关于APM(异步编程模型)的信息。基本上,我想做的就是调用一个APIf1()来完成一项功能(这需要花费8到10秒钟的时间),所以我将其称为APIf1(),将其忘掉,然后继续做其他事情工作,例如I / O,用于为下一次调用f1()或者某些不依赖于f1()结果的功能获取数据。

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

还有其他实现异步API的方式,任何其他可能有助于此目的的库/框架吗?

解决方案

回答

用指向C语言中函数的指针替换委托,其他所有内容与我们已阅读的内容基本相同。

回答

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

回答

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

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

如果我们打算仅在一个平台(例如Windows)上运行应用程序,并且f1()完成的工作是相对简单的事情,那么线程化就可以了。

回答

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

使用任何形式的事件循环的问题是,不了解循环的外部函数永远不会将控制权交还给循环。因此,我们将无能为力。

回答

出色地。基本上,我已经看到两种类型的异步API:

  • 打断。我们给呼叫提供了应在呼叫后执行的回调。 GIO(先前提到的GLib的一部分)以这种方式工作。使用它相对容易编程,但是通常会更改要在其中运行回调的线程(除非像GIO那样将其与主循环集成在一起)。
  • 轮询。我们检查数据是否可用。众所周知的BSD套接字以这种方式运行。它具有不必与主循环集成以及在特定线程中运行回调的优点。

如果我们为基于Gnome或者Gtk +的程序进行编程,我想补充一下,GTask看起来非常不错(可能不错?我没有使用过)。 Vala将对类似GIO的异步调用提供更好的支持。