2012-02-01 16 views
7

Estoy escribiendo una biblioteca en C#, pero necesito que sea asincrónica. Normalmente expones un conjunto de funciones de DLL, y toman parámetros de entrada, y devuelven un valor cuando terminan. Pero, ¿cómo puedo hacer que una función de biblioteca (que se puede llamar desde C++/Delphi/Etc) que ya comienza a reproducir de vuelta la salida mientras se toma la entrada?API asíncrona para transmitir datos desde un dispositivo de hardware

La única solución que veo ahora es comunicar usando sockets/pipes/etc, en lugar de llamadas a DLL.

¿Alguien tiene un ejemplo de cómo hacer esto con las llamadas a DLL normales?

+0

que realmente depende de lo que está haciendo ... incluso podría intercambiar punteros a funciones a las que su DLL llama cuando necesita el siguiente fragmento de entrada ... podría usar memoria compartida más un mutex global para intercambiar datos hacia adelante y hacia atrás, etc. Para obtener una respuesta útil, realmente necesita dar más detalles ... – Yahia

+2

Aquí hay varias opciones diferentes: en parte, depende del tipo de salida que tenga y de las entradas. Cuando escucho "asincrónico", tiendo a pensar en llamadas asincrónicas de un solo disparo, "Aquí hay alguna entrada, dame algo de salida cuando estés listo", pero esto parece que quieres una solución de transmisión de tipo más o menos. Más contexto sería útil. –

+0

Una opción es hacer que sus funciones tomen un parámetro de devolución de llamada al que puede llamar para procesar fragmentos de los datos de salida. Sin embargo, puede que no sea la API más conveniente. Una forma más natural sería devolver algún tipo de objeto iterador, pero eso haría que la implementación de su biblioteca sea más complicada, dependiendo de dónde provenga su entrada. – millimoose

Respuesta

0

de acuerdo con los comentarios de la OP la aplicación que llama envía audio a la DLL, el DLL envía salida de audio a través de alguna de las interfaces USB, la DLL captura algunas de audio desde la interfaz de micrófono y necesita enviar el audio capturado a la aplicación mientras el sensor de la aplicación DS audio a la DLL etc.

Basado en esto y el hecho de que la llamada puede ser escrito en diferentes idiomas rahter que veo algunas opciones para los canales de comunicación:

  • TCP/IP (en función de "escritorio configuración del firewall", etc. esto podría ser problemático!)
  • Tubos
  • objetos COM eventos/controladores de eventos
  • DLL con devolución de llamada aunque esto será un poco difícil de conseguir trabajo para todos los idiomas
  • memoria compartida con mutex globales (podría facilitar que para la aplicación de consumo, ofreciendo una función de "configuración" de la DLL que devuelve los punteros y los nombres de exclusión mutua)
1

Un buen modelo para una llamada de biblioteca asincrónica directa (que se encuentra en System.dll) es WebClient.DownloadStringAsync. Este método se descarga de manera asíncrona desde Uri y provoca el evento DownloadStringCompleted cuando termina.

Su biblioteca podría asimismo prever un método FooAsync, que no bloquea el flujo actual, pero provoca un evento cada vez que FooDataReceived algunos datos vienen a tu biblioteca y un evento FooCompleted siempre que los acabados de cálculo.

+1

que no tiene en cuenta que el OP quiere que ambas direcciones sean asincrónicas, es decir, al tiempo que da una salida Atrás, él quiere recibir entrada asincrónica también ... – Yahia

0

Hay un par de maneras de ir con esto. En la mayoría de los idiomas, puede realizar llamadas asincrónicas a métodos que utilizan subprocesos o despachadores. En general, siempre y cuando realice su dll re-entrant (capaz de dar servicio a múltiples hilos al mismo tiempo), el entorno de llamadas puede ocuparse de la parte asíncrona.

Sin embargo, es posible hornear las llamadas asíncronas en su API. Un ejemplo de algo que hace esto es el WCF client proxies.

0
  • Puesto que desea tanto de entrada como de salida para ser asíncrono, se necesita un hilo trabajador: Si ni el hilo de escribir, ni tampoco el que toma la salida puede ser bloqueado, ambos no pueden ser molestado para hacer el trabajo

  • Usted ya pensó en comunicarse a través de tuberías, pero ¿por qué usar una tubería y no una ranura interna?

  • Así que tienes esta cola sin bloqueo en la entrada, otro en la salida y un subproceso de trabajo

  • El subproceso de trabajo toma la entrada de la INQUEUE, lo procesa, lo pone en la outqueue

  • Si la cola de entrada se vacía, el subproceso de trabajo no tiene nada hacer cálculos sobre, por lo que plantea una "necesidad de más datos" evento y entonces bloquea en la cola de entrada convertirse (en parte), lleno

  • Si el subproceso de trabajo pone algo en la cola de salida, plantea un "have mo re evento de datos", y si la cola de salida se convierte en (totalmente) llena, bloques de espacio de salida haciendo disponibles

  • Su API es sin bloqueo: Ni el envío de entrada ni la recepción de la salida nunca bloquear

  • Su API es asíncrono : Notificaciones (vía Eventos) se dan

0

me gusta el siguiente enfoque, ya que hace que sea muy sencillo para los clientes.

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

Lo esencial es que una patada fuera un método en la biblioteca que devuelve de inmediato, a continuación, notifica a la persona que llama a través de un evento/delegado que el tratamiento se ha completado. A continuación, puede invocar nuevamente la ejecución en el subproceso de interfaz de usuario según sea necesario.

Obviamente, el manejo de errores no está incluido en el código de muestra.

+0

y ¿cómo funcionaría eso con/ser utilizable con C++, Delphi, etc.? – Yahia

+0

@Yahia C++ tiene un modo administrado que puede consumir construcciones de C# fácilmente. No he hecho nada con Delphi desde 1995, así que no pude comentar sobre eso. – AngryHacker

+0

Sí, pero entiendo por OP que la biblioteca debe poder utilizarse en varios idiomas, incluidos los nativos (Delphi es nativo pero puede usar COM, por ejemplo) ... – Yahia

Cuestiones relacionadas