Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

392
Views
Crear una tarea (u observable) a partir de una clase heredada (método de inicio + eventos)

Tengo una clase heredada que me gustaría consumir de una manera más conveniente.

 class Camera { void RequestCapture(); public delegate void ReadResultEventHandler(ControllerProxy sender, ReadResult readResult); public event ReadResultEventHandler OnReadResult; }

La clase maneja una cámara que toma fotografías. Funciona por:

  1. Invocando el método RequestCapture
  2. En espera de que se genere OnReadResult (obviamente, debe suscribirse a este evento para obtener los datos capturados)

La operación es asíncrona. RequestCapture es una operación de disparo y olvido (¡rápida!). Después de unos segundos, el evento se levantará.

Me gustaría consumirlo como una Task regular o como un IObservable<ReadResult> pero estoy bastante perdido, ya que no se adapta al Patrón Async, y nunca he usado una clase como esta.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Siguiendo el ejemplo de este artículo, mi enfoque rudimentario (¡no probado!) sería:

 class AsyncCamera { private readonly Camera camera; public AsyncCamera(Camera camera) { this.camera = camera ?? throw new ArgumentNullException(nameof(camera)); } public Task<ReadResult> CaptureAsync() { TaskCompletionSource<ReadResult> tcs = new TaskCompletionSource<ReadResult>(); camera.OnReadResult += (sender, result) => { tcs.TrySetResult(result); }; camera.RequestCapture(); return tcs.Task; } }

Posible uso:

 public async Task DoSomethingAsync() { var asyncCam = new AsyncCamera(new Camera()); var readResult = await asyncCam.CaptureAsync(); // use readResult }

EDITAR teniendo en cuenta el comentario de Stephen (¡GRACIAS!)

Entonces, esta es mi opinión ingenua sobre la cancelación de la suscripción al controlador de eventos. No tuve tiempo de hacer ninguna prueba, por lo que se aceptan sugerencias para mejorar.

 class AsyncCamera { private readonly Camera camera; public AsyncCamera(Camera camera) { this.camera = camera ?? throw new ArgumentNullException(nameof(camera)); } public Task<ReadResult> CaptureAsync() { ReadResultEventHandler handler = null; TaskCompletionSource<ReadResult> tcs = new TaskCompletionSource<ReadResult>(); handler = (sender, result) => { camera.OnReadResult -= handler; tcs.TrySetResult(result); }; camera.OnReadResult += handler; camera.RequestCapture(); return tcs.Task; } }

En caso de que los comentarios se "limpien": Stephen dijo

La cancelación de la suscripción no se maneja en los ejemplos de MS, pero realmente debería ser así. Tendría que declarar una variable de tipo ReadResultDelegate (o como se llame), establecerla en nulo y luego establecerla en la expresión lambda que luego puede cancelar la suscripción de esa variable del evento. No tengo un ejemplo de esto en mi blog, pero hay uno de propósito general aquí . Lo cual, ahora que lo miro, no parece manejar la cancelación de manera adecuada. – Stephen Cleary

Énfasis por mí.

Parece funcionar: https://dotnetfiddle.net/9XsaUB

over 4 years ago · Santiago Trujillo Report

0

Podría convertir el evento Camera.OnReadResult en una secuencia observable usando el operador FromEvent :

 var camera = new Camera(); IObservable<ReadResult> observable = Observable .FromEvent<Camera.ReadResultEventHandler, ReadResult>( h => (sender, readResult) => h(readResult), h => camera.OnReadResult += h, h => camera.OnReadResult -= h);

Alternativamente, podría usar el operador Create . Es más detallado, pero probablemente también más fácil de comprender.

 IObservable<ReadResult> observable = Observable.Create<ReadResult>(o => { camera.OnReadResult += Camera_OnReadResult; void Camera_OnReadResult(ControllerProxy sender, ReadResult readResult) { o.OnNext(readResult); } return Disposable.Create(() => camera.OnReadResult -= Camera_OnReadResult); });
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!