Reputation: 1449
I have been wondering...
Do the new Async constructs actually allow for intermediate results without writing new code on the consumer side?
Let me elaborate with an example.
Let's say we have a method that downloads data into a byte array or a stream, whichever is better.
Is it possible, that a method that await
s said method can start consuming the byte array or stream before the download is complete with the built in async features? What I could do is raise events everytime a certain part of the stream is downloaded, but that increases clutter again.
Let me write a code example (from the top of my head, will not be correct code!) that I (would) expect to result in intermediate results, given the await
ed method returns such results.
io.Stream data = await downloadData();
byte[4096] buffer = new byte[4096];
while (!data.EOF) {
(await?) data.Read(buffer, offset, 4096);
}
As of now, Stream.Read
is not awaitable, do we have any method of doing this, though? I want to be able to await
through a transfer. Am I overseeing anything?
Upvotes: 1
Views: 2381
Reputation: 13579
I'm not really familiar enough with it to give you a good example, but since it sounds like you don't want a one-time result, but instead multiple results, that sounds like a better fit for observable. Thenter link description hereis image from the Rx team's 2.0 beta blog post is extremely useful along those lines (IMHO).
Upvotes: 2
Reputation: 244868
If you're using Stream
in .Net 4.5, you can use its ReadAsync()
method for this:
Stream stream = await downloadData();
byte[4096] buffer = new byte[4096];
int read;
do
{
read = await stream.ReadAsync(buffer, 0, buffer.Length);
// do something with buffer here
} while (read > 0);
If you mean that your stream does not have a method such as ReadAsync()
, but does support asynchrony using the BeginXxx()
, EndXxx()
pattern, and you want to use await
, then you can do that too:
do
{
read = await Task.Factory.FromAsync<byte[], int, int, int>(
stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null);
// do something with buffer here
} while (read > 0);
But, if you only have a synchronous Read()
method, the only way to use it with async
would be to start a new Task
on a background thread:
do
{
read = await Task.Run(() => stream.Read(buffer, 0, buffer.Length));
// do something with buffer here
} while (read > 0);
The problem with this code is that it still blocks a thread, which is what async
is trying to avoid. But it might still be useful if the method runs on a GUI thread, and you can't run the whole loop on a background thread.
Upvotes: 2