I am creating an audio recorder control, with playback functionality.
I use the media element to play the recorded audio like this:
using (var storage = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
{
using (System.IO.Stream stream = new System.IO.IsolatedStorage.IsolatedStorageFileStream(filePath, System.IO.FileMode.Open, storage))
{
player.SetSource(stream);
}
}
The problem i am facing is that when I use media element to play the recorded audio. The Stream is locked to the media element. I cannot overwrite the file or even play it again as the SetSource()
method throws an exception.
Is there a way to force the media element to release the stream?
If you use MediaElement, make sure you don't get bitten by this one: http://msdn.microsoft.com/en-us/library/cc626563(v=vs.95).aspx
naturally one would expect, if they only use SetSource(somestream) to use SetSource(null) to release the resources. Nope, they thought "better", you have to use Source=null instead to release resources and SetSource(null) throws ArgumentNullException
that is what I call a design bug (breaks the rule of "least expected" behavior and causes bugs that bite you at runtime only [unless somebody has made a static analysis rule to catch such a thing - would need metadata of course that some argument can't be null, like in Code Contracts])
I managed to introduce this bug while refactoring some code in ClipFlair Studio's AudioRecorder control the other day :-(
Note that you can’t use at MediaElement something like Source = stream to open a Stream, since that is a Uri property (not an Object property to also accept Stream) and you have to use SetSource(stream) instead, so you’d also expect to be able to use SetSource(null) to release the resources.
Update: Fixed this in AudioRecorderView class (uses MVVM pattern) of AudioRecorderControl, at Audio property’s "set" accessor it needed the following null-guarding pattern:
Based on @Sheridan answer this it what I came up with that works.
Whenever
MediaElement
is stopped usingStop()
function set theSource
Property tonull
like this:This will close the stream attached to the media element, so that the related resource can be used somewhere else.
I had a similar problem with displaying images. In a control with an image, I would get a 'File is in use' error whenever the user tried to update the image. The solution was to set the
BitmapImage.CacheOption
property toBitmapCacheOption.OnLoad
:MSDN says Set the CacheOption to BitmapCacheOption.OnLoad if you wish to close a stream used to create the BitmapImage. The default OnDemand cache option retains access to the stream until the image is needed, and cleanup is handled by the garbage collector.
After searching for a similar property that you could use for your
MediaElement
, it turns out that there isn't one. However, according to an answer on the chacheoption for mediaelement post from MSDN, there is a (long winded) way to achieve this... from the relevant answer:I hope that this helps.