用于从硬件设备流式传输数据的异步API

时间:2012-02-01 18:41:01

标签: c# api dll interface asynchronous

我正在用C#编写一个库,但我需要让它异步。通常,您公开一组DLL函数,它们接受输入参数,并在完成时返回一个值。但是我怎样才能创建一个库函数(可以从C ++ / Delphi / Etc中调用),它在开始输入时已经开始流回输出?

我现在看到的唯一解决方案是使用套接字/管道/等进行通信,而不是使用DLL调用。

有人有一个例子如何使用普通的DLL调用吗?

6 个答案:

答案 0 :(得分:1)

直接异步库调用(位于System.dll)的一个好模型是WebClient.DownloadStringAsync。此方法异步下载Uri,并在完成时引发DownloadStringCompleted事件。

您的库同样可以提供FooAsync方法,该方法不会阻止当前线程,但只要有些数据进入您的库就会引发FooDataReceived事件,并且只要FooCompleted事件发生{{1}}事件计算结束。

答案 1 :(得分:0)

有几种方法可以解决这个问题。在大多数语言中,您可以使用线程或调度程序对方法进行异步调用。通常,只要你创建你的dll re-entrant(能够同时为多个线程提供服务),调用环境就可以处理异步部分。

但是,可以将异步调用烘焙到API中。执行此操作的一个示例是WCF client proxies

答案 2 :(得分:0)

微软在这件事上有一篇很好的文章。如果你只是在EndInvoke上移动它,它也应该适合你。 http://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.71).aspx

答案 3 :(得分:0)

  • 由于您希望输入和输出都是异步的,因此您需要一个 工作线程:如果既没有输入线程,也没有输入线程 输出可以被阻止,两者都不能打扰工作。

  • 您已经考虑过通过管道进行通信,但为​​什么要使用管道而不是内部结构?

  • 所以你在输入上有这个无锁队列,输出上有另一个队列和一个工作线程

  • 工作线程接收来自入队的输入,处理它,将其放入出队

  • 如果输入队列变空,那么工作线程没有什么可以处理,所以他引发了“需要更多数据”事件,然后在输入队列上阻塞变为(部分)完整

  • 如果工作线程将某些内容放入输出队列,则会引发“有更多数据”事件,如果输出队列变为(完全)满,则会阻止输出空间变为可用

    < / LI>
  • 您的API无阻塞:发送输入和接收输出都没有阻止

  • 您的API是异步的:通知(通过事件)

答案 4 :(得分:0)

根据OP的评论,调用应用程序向DLL发送音频,DLL通过某些USB接口发送音频,DLL从麦克风接口捕获一些音频,需要将捕获的音频发送回应用程序应用程序将音频发送到DLL等。

基于此以及呼叫可以用不同语言编写的事实我看到了一些通信渠道的选项:

  • TCP / IP(取决于“桌面防火墙设置”等,这可能会有问题!)
  • 包含事件/事件处理程序的COM对象
  • 带有回调的DLL,虽然这对于所有语言来说都有点难以实现
  • 与全局互斥锁共享内存(通过从返回指针和互斥锁名称的DLL中提供“设置”功能,可以简化消费应用程序)

答案 5 :(得分: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线程。

显然,错误处理不包含在示例代码中。