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

267
Visualizações
async Task <IEnumerable> con retorno de rendimiento?

El siguiente método no compila. ¿Alternativas?

 public static async Task<IEnumerable<object[]>> GetRecordsAsync( this Transaction transaction, string commandText, params SqlParameter[] parameters) { // Get a SqlDataReader var reader = await transaction.GetReaderAsync(commandText, parameters); var fieldCount = -1; // Begin iterating through records asynchronously while (await reader.ReadAsync()) // Note we don't loop until .ReadAsync returns a boolean { // Grab all the field values out if (fieldCount < 0) fieldCount = reader.FieldCount; var fields = new object[fieldCount]; reader.GetValues(fields); // Yield return the field values from this record yield return fields; } }

Mensaje de error:

El cuerpo de 'TransactionExtensions.GetRecordsAsync(Transaction, string, params SqlParameter[])' no puede ser un bloque de iterador porque 'Task>' no es un tipo de interfaz de iterador

No veo una manera de adaptar esta respuesta a una pregunta que suena similar (pero diferente), porque no sé a priori cuántas veces irá el bucle.

Editar: formato fijo

about 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Basado en el comentario de @SLaks a la pregunta, aquí hay una alternativa general usando Extensiones reactivas :

 /// <summary> /// Turns the given asynchronous functions into an IObservable /// </summary> static IObservable<T> ToObservable<T>( Func<Task<bool>> shouldLoopAsync, Func<Task<T>> getAsync) { return Observable.Create<T>( observer => Task.Run(async () => { while (await shouldLoopAsync()) { var value = await getAsync(); observer.OnNext(value); } observer.OnCompleted(); } ) ); }

Ejemplo de uso, adaptado para resolver el caso específico de la pregunta:

 /// <summary> /// Asynchronously processes each record of the given reader using the given handler /// </summary> static async Task ProcessResultsAsync(this SqlDataReader reader, Action<object[]> fieldsHandler) { // Set up async functions for the reader var shouldLoopAsync = (Func<Task<bool>>)reader.ReadAsync; var getAsync = new Func<SqlDataReader, Func<Task<object[]>>>(_reader => { var fieldCount = -1; return () => Task.Run(() => { Interlocked.CompareExchange(ref fieldCount, _reader.FieldCount, -1); var fields = new object[fieldCount]; _reader.GetValues(fields); return fields; }); })(reader); // Turn the async functions into an IObservable var observable = ToObservable(shouldLoopAsync, getAsync); // Process the fields as they become available var finished = new ManualResetEventSlim(); // This will be our signal for when the observable completes using (observable.Subscribe( onNext: fieldsHandler, // Invoke the handler for each set of fields onCompleted: finished.Set // Set the gate when the observable completes )) // Don't forget best practice of disposing IDisposables // Asynchronously wait for the gate to be set await Task.Run((Action)finished.Wait); }

(Tenga en cuenta que getAsync podría simplificarse en el bloque de código anterior, pero me gusta lo explícito que es sobre el cierre que se está creando)

...y finalmente:

 // Get a SqlDataReader var reader = await transaction.GetReaderAsync(commandText, parameters); // Do something with the records await reader.ProcessResultsAsync(fields => { /* Code here to process each record */ });
about 4 years ago · Santiago Trujillo Relatório

0

No devuelva Task<IEnumerable<T>> y ni siquiera use Task para esto; en su lugar, devuelva un IAsyncEnumerable<T> . No se necesitan bibliotecas de terceros u otras soluciones alternativas, ni siquiera es necesario alterar el cuerpo de su método original.

 public static async IAsyncEnumerable<object[]> GetRecordsAsync( this Transaction transaction, string commandText, params SqlParameter[] parameters) { // Get a SqlDataReader var reader = await transaction.GetReaderAsync(commandText, parameters); var fieldCount = -1; // Begin iterating through records asynchronously while (await reader.ReadAsync()) // Note we don't loop until .ReadAsync returns a boolean { // Grab all the field values out if (fieldCount < 0) fieldCount = reader.FieldCount; var fields = new object[fieldCount]; reader.GetValues(fields); // Yield return the field values from this record yield return fields; } }
about 4 years ago · Santiago Trujillo Relatório

0

Lo resolví sin extensiones de terceros:

 public async Task<IEnumerable<Item>> GetAllFromDb() { OracleConnection connection = null; DbDataReader reader = null; try { connection = new OracleConnection(connectionString); var command = new OracleCommand(queryString, connection); connection.Open(); reader = await command.ExecuteReaderAsync(); return this.BuildEnumerable(connection, reader); } catch (Exception) { reader?.Dispose(); connection?.Dispose(); throw; } } private IEnumerable<Item> BuildEnumerable(OracleConnection connection, DbDataReader reader) { using (connection) using (reader) { while (reader.Read()) { var item = new Item() { Prop = reader.GetString(0), }; yield return item; } } }

Este ejemplo es para Oracle Data Reader pero el mismo enfoque es aplicable a cualquier operación asíncrona combinada con yield return

about 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