9
votes

I'm getting the above exception and error on the following code, which is meant to play a selected mp3 file from Isolated Storage:

using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
{            
     using (var isfs = isf.OpenFile(selected.Path, FileMode.Open))
     {                        
          this.media.SetSource(isfs);              
          isfs.Close();                        
     }                    
     isf.Dispose();
}

The error is so vague that I'm not really sure what could be wrong... Any ideas or at least common sources of this error that I could potentially check for?

EDIT: the exception is being thrown at: using(var isfs = isf.OpenFile(...))

EDIT 2: The stack trace...

at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, IsolatedStorageFile isf)
at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, IsolatedStorageFile isf)
at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, IsolatedStorageFile isf)
at Ringify.Phone.PivotContent.RingtoneCollectionPage.MediaIconSelected(Object sender, GestureEventArgs e)
at MS.Internal.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)

I've realized too that the error does NOT occur if I play one song then stop it (there is a play and pause button in the UI), then play another song. It occurs when I play one song, stop it, and attempt to play the same song again.

2
Which instruction is triggering the error, isf.OpenFile? If so, make sure that the file exists. You can check by calling isf.FileExists(selected.Path) before opening the fileKevin Gosse
Yes, it's that line. I did an informal check by writing to console the results of isf.FileExists(selected.Path) since I thought maybe that was the case, but it does and putting in a an actual if-statement doesn't solve the problem.Amy Li
I can't think of any reason why this code would throw an exception with an existing file. Can you show us the value of selected.Path?Kevin Gosse
selected.Path just returns an appended version of the folder name (ie: music) and file name (ie: song1.mp3) in isolated storage, based on a pre-created folder and a pre-saved file. So for example: "music/song1.mp3"Amy Li

2 Answers

8
votes

The problem occurs when you play the same music twice, therefore it may be a file sharing problem. You should try to provide the FileShare parameter of the OpenFile method:

var isfs = isf.OpenFile(selected.Path, FileMode.Open, FileShare.Read)

Though I don't understand why it would happen, since you're explicitly closing the file.

EDIT: OK, did some digging with Reflector, and I figured it out. The code of MediaElement.SetSource is:

public void SetSource(Stream stream)
{
    if (stream == null)
    {
        throw new ArgumentNullException("stream");
    }
    if (stream.GetType() != typeof(IsolatedStorageFileStream))
    {
        throw new NotSupportedException("Stream must be of type IsolatedStorageFileStream");
    }
    IsolatedStorageFileStream stream2 = stream as IsolatedStorageFileStream;
    stream2.Flush();
    stream2.Close();
    this.Source = new Uri(stream2.Name, UriKind.Absolute);
}

So basically it doesn't use the stream you give, and it even closes it. But it keeps the name of the file, and I guess it re-opens it when you play the music. Therefore, if you try to re-open the same file with exclusive access while the music is playing, it fails because the MediaElement has the file opened. Tricky.

1
votes

I believe you should be using an IsolatedStorageFileStream:

using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
{            
     using (var isfs = new IsolatedStorageFileStream(selected.Path, FileMode.Open, isf))
     {                        
          this.media.SetSource(isfs);              
     }                    
}

Also, note that you do not need to call the .Close() or .Dispose() methods as they are taken care of in the using statements.