UnauthorizedAccessException in StorageFile.OpenAsync

I used the following code to load / save the image and open it later, but in later OpenAsync it throws a UnauthorizedAccessException, it seems that the file is not close, but IRandomAccessStream / DataWriter was actually set.

HttpClient httpClient = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://www.silverlightshow.net/Storage/Users/nikolayraychev/Perspective_Transforms_4.gif"); HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); //Write Image File StorageFile imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("test.gif", CreationCollisionOption.ReplaceExisting); using (IRandomAccessStream fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite)) { using (DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0))) { writer.WriteBytes(await response.Content.ReadAsByteArrayAsync()); await writer.StoreAsync(); writer.DetachStream(); await fs.FlushAsync(); } } StorageFile imageFile1 = await ApplicationData.Current.LocalFolder.GetFileAsync("test.gif"); //Exception is throwed here using (IRandomAccessStream stream = await imageFile1.OpenAsync(FileAccessMode.Read)) { BitmapImage img = new BitmapImage(); img.SetSource(stream); } 
+4
source share
3 answers

I had the same problem and I had to explicitly delete the stream and file objects before it completed.

  var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, Windows.Storage.CreationCollisionOption.ReplaceExisting); using (var fs = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite)) { var outStream = fs.GetOutputStreamAt(0); var dataWriter = new Windows.Storage.Streams.DataWriter(outStream); dataWriter.WriteString("Hello from Test!"); await dataWriter.StoreAsync(); dataWriter.DetachStream(); await outStream.FlushAsync(); outStream.Dispose(); // fs.Dispose(); } 
+6
source

You cannot β€œuse” when using β€œwait”. The reason is how the compiler converts your C # wait / asynchronously to IL. You can decompile it.

When the processor reaches:

 await writer.StoreAsync(); 

in fact, he immediately returns to the caller (see IL). Since you use "use", the Dispose interface is called "IRandomAccessStream fs and the resources are freed. These resources are required by the thread initiated in" StoreAsync ".

For this reason, you must invoke Dispose explicitly after waiting.

The same problem occurs in try / exception / catch blocks.

0
source

It seems to me that you are skipping the stream passed to

  using (DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0))) 

If the stream is counted by reference (this, after all, is winRT), then the link will be held by the temporary object passed to the constructor and incremented using the constructor in the DataWriter.

A temporary object is awaiting garbage collection.

Does it work if you do this:

 using (var st0 = fs.GetOutputStreamAt(0)) using (DataWriter writer = new DataWriter(st0)) 
0
source

All Articles