2012-02-01 24 views
7

我正在用C#編寫一個庫,但我需要使其成爲異步。通常你公開一組DLL函數,並且它們需要輸入參數,並在完成時返回一個值。但是我怎樣才能創建一個庫函數(可以從C++/Delphi/Etc調用),在輸入的同時已經開始流回輸出?用於流硬件設備數據的異步API

我現在看到的唯一解決方案是使用套接字/管道/ etc來進行通信,而不是使用DLL調用進行通信。

有人有一個例子如何做到這一點與正常的DLL調用?

+0

確實取決於你在做什麼......你甚至可以交換指向函數的指針,當你的DLL需要下一個輸入塊時可以調用它......你可以使用共享內存加全局互斥來交換數據爲了得到一個有用的答案,你真的需要提供更多的細節...... – Yahia 2012-02-01 18:44:19

+2

這裏有各種不同的選擇 - 它部分取決於你得到了什麼樣的輸出,以及輸入是什麼樣的。當我聽到「異步」時,我傾向於考慮一次性異步調用,「這裏有一些輸入,當你準備好時給我一些輸出」,但這聽起來像你可能需要更多的流式解決方案。更多的上下文將是有用的。 – 2012-02-01 18:44:23

+0

一種選擇是讓你的函數帶一個回調參數,你可以調用它來處理輸出數據的塊。它可能不是最方便的API。更自然的方式是返回某種迭代器對象,但這會使得實現您的庫變得更加複雜,這取決於它的輸入來自哪裏。 – millimoose 2012-02-01 18:44:48

回答

0

據來自OP調用應用程序將音頻發送到DLL的意見,DLL將通過一些USB接口音頻輸出,該DLL捕獲從麥克風接口部分音頻並且需要在應用程序發送時將捕獲的音頻發送迴應用程序DS音頻的DLL等

在此基礎上,事實上,主叫可以在rahter不同的語言我看到了溝通渠道的一些選項可以寫成:

  • TCP/IP(根據「桌面上防火牆設置」等,這可能是有問題的!)
  • 管道
  • 與活動/事件處理程序
  • DLL有回調的COM對象,儘管這將是一個有點難以得到工作的所有語言
  • 全球互斥共享內存(可以緩解,對於通過提供從DLL中的「設置」功能的消費應用程序,它返回的指針和互斥名)
1

簡單的異步庫調用(位於System.dll)的一個很好的模型是WebClient.DownloadStringAsync。該方法異步下載Uri,並在其完成時引發DownloadStringCompleted事件。每當一些數據進入你的圖書館和一個FooCompleted事件每當計算完成

你的庫同樣可以提供FooAsync方法,它不會阻止當前線程,但提出了一個FooDataReceived事件。

+1

,不考慮到OP需要兩個方向的異步 - 即當給一些輸出回想他也想接受輸入異步... – Yahia 2012-02-01 18:50:16

0

有幾種方法可以解決這個問題。在大多數語言中,您可以使用線程或調度程序對方法進行異步調用。一般來說,只要你讓你的dll re-entrant(能夠同時處理多個線程),調用環境可以處理異步部分。

但是,可以將異步調用燒入API。一個這樣做的例子是WCF client proxies

0
  • 既然你想輸入和輸出是異步,您將需要一個 工作線程:如果既沒有輸入線,也不是一個以 輸出可以被阻止,既不能被人打擾做這項工作。

  • 你已經想過通過管道進行通訊,但爲什麼使用管道而不是內部結構?

  • 所以,你必須輸入這個無鎖隊列,另一個在輸出和輔助線程

  • 工作者線程需要輸入從進入隊列,處理它,將其放入outqueue

  • 如果輸入隊列變空,工作線程無關緊縮,所以他提出了一個「需要更多的數據」在輸入隊列事件,然後塊變成(部分)全

  • 如果工作線程把一些東西放在輸出隊列中,他提出了一個「重數據」事件,如果輸出隊列變(完全)成爲輸出空間滿了,他塊可用

  • 你的API是非阻塞:無論是發送到輸入信號或接收輸出永遠阻止

  • 你的API是異步:通知(通過活動)給出

0

我喜歡下面的方法,因爲它使得它非常簡單客戶。

// your library 
class Foo { 
    public event EventHandler ComputeCompleted = (sender, e) => { }; 

    public void Compute() { 
     // kick off work on a background thread 
     // possibly using the BackgroundWorker object 
     var bw = new BackgroundWorker();  
     bw.RunWorkerCompleted += RunWorkerCompleted; 
     bw.RunWorkerAsync(); 
    } 

    private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
     ComputeCompleted(this, new object()); 
    } 
} 

// calling code 
Foo foo = new Foo(); 
foo.ComputeCompleted += Completed; 
foo.Compute(); 

private void Completed(object Sender, EventArgs e) { 
    // process the result here 
} 

要點是,您在返回馬上圖書館揭開序幕的方法,然後通過一個事件/委託的處理完成通知調用者。然後您可以根據需要自由地將執行回調到UI線程。

顯然,錯誤處理不包含在示例代碼中。

+0

以及如何與C++,delphi等一起使用/可用? – Yahia 2012-02-01 19:33:58

+0

@Yahia C++有一個可以輕鬆使用C#構造的託管模式。自1995年以來,我沒有對德爾福做過任何事情,所以我不能對此發表評論。 – AngryHacker 2012-02-01 19:38:59

+0

是的,但我從OP瞭解到,該庫應該可用於多種語言,包括本地語言(Delphi是本地語言,但可以使用COM)... – Yahia 2012-02-01 19:44:07