I found a similar question to mine, but unfortunately it did not have an answer.
I'm using the StorageFile class in C# to create, write, then delete a file repetitively. On my second iteration, it fails to create the file, returning an access denied error.
Here is a simple unit test I put together in Visual Studio 2015 to demonstrate the problem:
[TestMethod]
public async Task DeleteTest()
{
StorageFolder folder = Windows.Storage.ApplicationData.Current.LocalFolder;
byte[] array = System.Text.Encoding.ASCII.GetBytes("Test data");
int i = 1, max = 20;
string phase = "not started";
try
{
do
{
// create file
phase = "creating";
StorageFile file = await folder.CreateFileAsync("test" /*,CreationCollisionOption.GenerateUniqueName*/);
// write data to the file
phase = "opening";
System.IO.Stream stream = await file.OpenStreamForWriteAsync();
phase = "writing";
await stream.WriteAsync(array, 0, array.Length);
phase = "flushing";
await stream.FlushAsync();
// delete file
phase = "deleting";
await file.DeleteAsync();
} while (++i <= max);
}
catch(Exception e)
{
Assert.Fail("While '{0}' on iteration {1}: {2}", phase, i, e.Message);
}
}
The Assertion above fires, reporting:
While 'creating' on iteration 2: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
If anyone can let me know what I am doing wrong, I'd appreciate it. I'm at my wits end with this.
Certain library features such as file stream access make use of unmanaged resources, that must be properly cleaned up before the object handle can be destroyed. This avoids situations such as when files are open in background even after the program is done executing and prevents them from being modifiable, etc.
In case of System.IO
and related functionality, Microsoft recommends that you call the Dispose()
or Close()
method that does exactly that. In your case, it is most likely that the file cannot be deleted successfully since it is open via the Stream
object.
Hence, adding Dispose()
after Flush()
on the Stream
should resolve the problem.
NOTE: Dispose()
automatically calls Flush()
, so an explicit call is redundant.