Return data from datareader asynchronously

I'm new to asynchronous stuff and I'm having a lot of problems trying to get this to work:

I am trying to load a large result set from SQL, which is what I want when I run the code below:

public async override IEnumerable<DataResult> Read()
{
    using (SqlConnection objConn = new SqlConnection(Options.GetConnectionString()))
    {
        await objConn.OpenAsync();
        SqlCommand comm = new SqlCommand(Options.SqlText, objConn);
        SqlDataReader reader = await comm.ExecuteReaderAsync();

        while (await reader.ReadAsync())
            yield return new DataResult { Reader = reader };
    }
}

      

Manufacturer Code:

BlockingCollection<DataResult> DataCollection = new BlockingCollection<DataResult>();

var producer = new Producer<DataResult>(() =>
{
    using (var sequenceEnum = sourceEngine.Read().GetEnumerator())
    {
        while (sequenceEnum.MoveNext())
            return sequenceEnum.Current;
    }
    return null;
}, DataCollection);
producer.Start();

      

That it returns data when it writes it to the record by record to the producer, who will store that data in BlockingCollection

for consumption by the consumer.

How can I get this code to work for what I expect from it?

+3


source to share


2 answers


Your signature is Read

not asynchronous:

public override IEnumerable<DataResult> Read();

      

Any implementation of this method must be synchronous. So you can only implement it with yield

and not use async

/ await

at all.

If you want it to be asynchronous, change Read

to ReadAsync

:



public override Task<IEnumerable<DataResult>> ReadAsync();

      

which you can implement (asynchronously) on a list and then return that list.

However, if what you really want is an asynchronous sequence (processing each piece of data as it comes in), then you should use Rx:

public override IObservable<DataResult> Read();

      

+3


source


You, unfortunately, cannot yield

from the method async

. By marking it as async

, you need to return void

, Task

or Task<T>

and this will prevent yield

the method from being created in the body.



You might come back IEnumerable<Task<T>>

by returning whatever you previously expected instead of using await

(you won't be able to use async

/ await

in this method anymore ).

0


source







All Articles