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

209
Visualizações
IAsyncEnumerable para flujo interminable

Estoy creando un cliente para consumir continuamente nuevos registros de una fuente de datos. La integración se basa en extracción y mi cliente consulta periódicamente la fuente de datos en busca de nuevos registros. Estoy usando IAsyncEnumerable como tipo de devolución para este flujo continuo de nuevos registros. Aquí está la esencia del método en cuestión:

 public async IAsyncEnumerable<Record> StreamRecords(...) { while (!cancellationToken.IsCancellationRequested) { using var response = await _httpClient.SendAsync(request, cancellationToken); var records = _parser.Parse(response.Content); foreach (var r in records) yield return r; await Task.Delay(waitPeriod, cancellationToken); } }

¿Es este un uso apropiado de IAsyncEnumerable? Esta secuencia debe ser "interminable" o "continua" (al menos hasta el token de cancelación o el error).

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Como con la mayoría de las cosas: el punto clave es que la intención y el comportamiento se comuniquen claramente. No veo ningún problema conceptual sobre una secuencia sin fin, ya sea IEnumerable<T> o IAsyncEnumerable<T> , pero obviamente si el consumidor llama a ToList[Async]() , las cosas terminarán mal. Esto no es un problema en sí mismo, para dar un escenario similar: algunas secuencias I[Async]Enumerable<T> no son repetibles , ya sea que solo se pueden iterar una vez (con intentos posteriores fallidos), o podrían producir resultados diferentes cada uno tiempo (sin siquiera requerir cosas como cambios en la lista). Esto es perfectamente legal, pero existe un código que asume que las secuencias son repetibles y producirán los mismos datos . La misma discusión existe aquí y, en última instancia, no es culpa del productor , sino del consumidor .

Entonces: su secuencia (productor) funcionará perfectamente bien con un consumidor razonable que entienda que los datos deben tratarse como ilimitados. Si eso es lo que tiene su aplicación, entonces: ¡genial!

over 4 years ago · Santiago Trujillo Relatório

0

Su método StreamRecords devuelve esencialmente una secuencia de consumo, de naturaleza similar a las secuencias devueltas por los métodos BlockingCollection<T>.GetConsumingEnumerable y ChannelReader<T>.ReadAllAsync . Consumir significa que cuando la persona que llama enumera la secuencia, los elementos devueltos se eliminan permanentemente de algún almacenamiento de respaldo. En el caso de estos dos métodos, el almacenamiento de respaldo es un ConcurrentQueue<T> interno. En su caso (según este comentario), el almacenamiento de respaldo se encuentra en el lado del servidor, con algún código del lado del cliente que sabe qué datos buscar a continuación.

Exponer una secuencia de consumo conlleva algunos desafíos:

  1. ¿Debe el método tener la palabra Consumidor o Destructivo como parte de su nombre?
  2. ¿Qué sucede en caso de cancelación? ¿La secuencia responde lo suficiente cuando llega una señal de cancelación? ¿Se cumplen las expectativas de la persona que llama?
  3. ¿Qué sucede si la persona que llama abandona la enumeración prematuramente, ya sea break o return deliberadamente del ciclo await foreach , o involuntariamente por una excepción transitoria lanzada dentro del ciclo? ¿Hay algún elemento consumido en peligro de perderse?

Con respecto al 1er desafío, puede leer este problema de GitHub, o mejor aún, ver este video , donde se debatieron las diversas opciones. Alerta de spoiler, los ingenieros de Microsoft se conformaron con el aparentemente inocuo ReadAllAsync .

Con respecto al segundo desafío, puede leer esta pregunta, que muestra que la decisión (técnicamente justificada) tomada por Microsoft con respecto a la API ChannelReader<T>.ReadAllAsync resultó en un comportamiento inesperado/no intuitivo.

Con respecto al tercer desafío, podría considerar aprovechar la mecánica de los bloques finally dentro de los métodos del iterador. Mira esta respuesta para más detalles.

Debido a estos matices, podría ser una buena idea brindar opciones de consumo adicionales a las personas que llaman. Algo así como public Task<Record[]> TakeAllNewRecords() por ejemplo.

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