Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataReader.loadAsync is being completed even when unconsumedBufferLength is 0

I'm consuming JSON stream on UWP WinRT with this code:

async function connect() {
    let stream: MSStream;
    return new CancellableContext<void>(
        async (context) => {
            // this will be called immediately
            stream = await context.queue(() => getStreamByXHR()); // returns ms-stream object
            await consumeStream(stream);
        },
        {
            revert: () => {
                // this will be called when user cancels the task
                stream.msClose();
            }
        }
    ).feed();
}

async function consumeStream(stream: MSStream) {
    return new CancellableContext<void>(async (context) => {
        const input = stream.msDetachStream() as Windows.Storage.Streams.IInputStream;
        const reader = new Windows.Storage.Streams.DataReader(input);
        reader.inputStreamOptions = Windows.Storage.Streams.InputStreamOptions.partial;

        while (!context.canceled) {
            const content = await consumeString(1000);
            // ... some more codes
        }

        async function consumeString(count: number) {
            await reader.loadAsync(count); // will throw when the stream gets closed
            return reader.readString(reader.unconsumedBufferLength);
        }
    }).feed();
}

Here, the document about InputStreamOptions.partial says:

The asynchronous read operation completes when one or more bytes is available.

However, reader.loadAsync completes even when reader.unconsumedBufferLength is 0 and this makes CPU load. Is this an API bug or can I prevent this behavior so that loadAsync can complete only when unconsumedBufferLength is greater than 0?

PS: Here is a repro with pure JS: https://github.com/SaschaNaz/InputStreamOptionsBugRepro

like image 720
Kagami Sascha Rosylight Avatar asked Feb 20 '16 18:02

Kagami Sascha Rosylight


1 Answers

Is this an API bug or can I prevent this behavior so that loadAsync can complete only when unconsumedBufferLength is greater than 0

Most likey it also completes at the end of stream. So in that case the unconsumedBufferLength will be zero and needs to be catered for.

In fact the example at https://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.streams.datareader.aspx shows something similar (admittedly not using that option):

            // Once we have written the contents successfully we load the stream.
            await dataReader.LoadAsync((uint)stream.Size);

            var receivedStrings = "";

            // Keep reading until we consume the complete stream.
            while (dataReader.UnconsumedBufferLength > 0)

🌹

like image 92
basarat Avatar answered Sep 24 '22 14:09

basarat