Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

402
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda