2012-02-01 46 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