The StorageFile.CreateStreamedFileAsync is a pretty neat mechanism that allows you to take a stream and use it like an IStorageFile. This is useful in a number of scenarios – especially ones where you are communicating with the OS or other apps (such as when using the share charm) and the “currency” used are StorageFile objects.
One thing you could do is simply write your streams into temporary files and hand those temporary files when needed. There’s a bunch of unnecessary IO happening in these cases – you write to disk and another app reads from disk where all you really want to do is straight up pass a stream.
I needed to use this method for an app, but something felt fishy about it.. Here’s the signature of the method:
And the signature for the StreamedFileDataRequestedHandler callback:
The idea is simple – you call the CreateStreamedFileAsync() method and it returns a StorageFile object which is not fully realized yet.
When the caller tries to access the StorageFile, it will activate the callback that will take a StreamedFileDataRequest instance which will be used provide the content of the file.
But here lies the rub… There’s no obvious “completion” semantics for the call. The class passed in has no “complete” method like other mechanisms in WinRT seem to have. When called, how will the OS know that the file completed streaming?
I searched the web, StackOverflow, MS forums and the like. While there are a few people who inquire about it, there’s no clear answer. I have not been able to find any answer. And MSDN does not have any examples on how to use this.
It took me longer than I’d care to admit, but it finally dawned on me that there is indeed a completion semantics here – each stream can be closed (or disposed) and that can be used as the explicit completion semantics. A few minutes of work and what’d’ya know? That’s how you are supposed to use it!
Here’s what the code looks like. First, the code that creates and uses the StorageFile instance (note that I am using the most simplistic example I could think of – an example that doesn’t really need to use this mechanism but requires very little code):
The first call we make will create the streamed file, passing in the FileGrabber callback (shown below). We then use a picker to prompt the user for a file to save and we copy our streamed file into the picked file.
Here’s the interesting bit:
The call takes a StreamFileDataRequest which is an IOutputStream derivative (among others).
What we do then is as follows:
- We transform the stream into a .NET stream (by calling .AsStreamForWrite()).
- We create a writer on top of it.
- We then write into the stream we got from the OS the content we want saved.
- Then – when we are done, we Dispose() of the request which will signal the OS that we are done (this bit is important since, as you can see, we are awaiting for WriteLineAsync() to complete – if there was no completion semantics, the OS would think it was done as soon as that first await was hit.
- On failure, we make sure to call FailAndClose().
That’s it pretty much! Hopefully you find this and it saves you a bit of time.