2008-09-15 41 views
1

當試圖實現一個異步API調用/非阻塞調用時,我在All Plain-C應用程序中瞭解了一點,我通過'委託'讀了一個關於APM(異步編程模型)的內容。基本上我想要做的是調用一個API f1()來完成一項功能(需要很長的時間8-10秒),所以我稱之爲API f1(),忘記它,然後繼續做其他工作,例如, I/O用於獲取下一個f1()調用的數據或某些不依賴於f1()的結果的功能。異步API

如果任何人使用該APM模型的編程,我正在尋找一些簡明的解釋來實現非阻塞調用。

是否有任何其他的方式來實現異步API,任何其他庫或框架可能有助於此?

回答

0

用C中指向函數的指針替換委託,其他一切與你讀過的基本相同。

1

您基本上需要創建一個多線程(或多進程)應用程序。 f1()API需要生成一個線程(或進程)來處理獨立執行空間中的數據。當它完成時,f1()例程需要通知主進程執行完成(signal(),消息隊列等)。

1

一個在普通C程序中進行異步編程的流行方式是使用「事件循環」。有許多庫可以使用。我建議看看 glib

另一種替代方法是使用多個預佔線程(每個併發操作一個線程),並將它們與互斥鎖和條件變量同步。然而,在普通C中的先發制人的線程是我會避免的,特別是如果你想編寫可移植的程序。很難知道哪些庫函數是可重入的,線程化程序中的信號處理是一件麻煩事,一般來說C庫和系統函數都是爲單線程使用而設計的。

如果您打算只在一個平臺(如Windows)上運行應用程序,並且使用f1()完成的工作是一件相對簡單的事情,那麼線程就可以。

1

如果您所指的函數f1()本身不是以異步方式實現的,則需要自行將其包裝在自己的線程中。在做這件事情時,您需要注意可能由被調用的特定功能引起的副作用。許多庫不是以線程安全的方式設計的,並且來自這些庫的多個函數的併發調用將導致數據損壞。在這種情況下,您可能需要在外部工作進程中完成功能。對於您提到的繁重(8-10秒),可能會接受開銷。如果您一次只在一個線程中使用外部非線程安全功能,則可能是安全的。

使用任何形式的事件循環的問題是不知道你的循環的外部函數永遠不會控制回到你的循環。因此,你不會做任何事情。

0

好吧。基本上我見過兩種異步API:

  1. 中斷。你給一個電話一個回調,應該在電話後執行。 GIO(前面提到的GLib的一部分)以這種方式工作。編程相對容易,但您通常會在其中調用回調的線程發生更改(除非與GIO一樣與主循環集成)。
  2. 民意調查。你檢查數據是否可用。衆所周知的BSD套接字以這種方式運行。它具有不一定與主循環集成並在特定線程中運行回調的優點。

如果你編寫基於Gnome或Gtk +的程序,我想補充說GTask似乎是一個非常好的(可能很好?我沒有用過它)。 Vala將更好地支持GIO類似的異步調用。