Asynchronous API for streaming data from a hardware device

I am writing a library in C #, but I need to make it asynchronous. Typically, you provide a set of DLL functions, and they take input parameters and return a value when completed. But how can I make a library function (called from C ++ / Delphi / Etc) that already starts streaming output while still accepting the input?

The only solution that I see now is communication using sockets / pipes / etc. instead of DLL calls.

Does anyone have an example on how to do this with regular DLL calls?

+7
source share
6 answers

According to OP's comments, the calling application sends audio to the DLL, the DLL sends audio through some USB interface, the DLL captures some audio signals from the microphone interface and requires that the captured sound be sent back to the application, while the application sends audio to the DLL, etc. .

Based on this and the fact that the call can be recorded in different languages, I see several options for communication channels:

  • TCP / IP (depending on the settings of desktop firewalls, etc. this can be problematic!)
  • Pipes
  • COM objects with events / event handlers
  • Callback dlls though it will be a little tricky to work in all languages
  • shared memory with global mutexes (this can be made easier for a consumer application by proposing the "setup" function from a DLL that returns the names of pointers and mutexes)
0
source

One good model for a simple asynchronous library call (which is located in System.dll ) is WebClient.DownloadStringAsync . This method is loaded from Uri asynchronously and raises the DownloadStringCompleted event whenever it ends.

Your library can also provide the FooAsync method, which does not block the current stream, but raises the FooDataReceived event whenever some data arrives in your library and the FooCompleted event whenever the calculation ends.

+1
source

There are several ways to go about this. In most languages, you can make asynchronous calls to methods using threads or dispatchers. In general, as long as you create your re-entrant dll (capable of serving multiple threads at the same time), the calling environment can take care of the asynchronous part.

However, you can bake asynchronous calls to your API. An example of what this does is WCF clicks .

0
source

Microsoft has a good article on this. If you just move on EndInvoke, it should work for you too. http://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.71).aspx

0
source
  • Since you want both inputs and outputs to be asynchronous, you will need a workflow: if neither the input stream nor the one that accepts the output can be blocked, both cannot be bothered by work.

  • You’ve already thought about communicating through channels, but why use a channel, not an internal strcuture?

  • So, you have this free queue at the entrance, another at the exit and the workflow

  • Workflow receives input from the queue, processes it, puts it in the queue

  • If the input queue becomes empty, the workflow has nothing to crackle, so it raises the “need more data” event, and then blocks the input queue, becoming (partially) full.

  • If a worker thread places something in the output queue, it raises the “have more data” event, and if the output queue becomes (completely) full, it blocks the available output space

  • Your API is not blocked: neither sending input nor receiving output is ever blocked

  • Your API is asynchronous: notifications (via events) are given

0
source

I like the following approach because it makes it very easy for customers.

 // 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 } 

The bottom line is that you run the method in the library, which immediately returns, and then notifies the caller through the event / delegate of the completion of processing. Then you can call execution for free on the user interface thread.

Obviously, error handling is not included in the sample code.

0
source

All Articles