Daz Eddy
Daz Eddy

Reputation: 362

Win Universal: UnauthorizedAccessException opening new stream for writing

A customer is reporting an issue with the following code:

public static async Task<Stream> CreateAsync(string path)
        {
            StorageFolder folder = await Directory.GetFolderAsync(Path.GetDirectoryName(path));
            StorageFile file = await folder.CreateFileAsync(Path.GetFileName(path), CreationCollisionOption.ReplaceExisting);
            return await file.OpenStreamForWriteAsync();
        }

The exception they are getting is:

System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.IO.WindowsRuntimeStorageExtensions..<OpenStreamForWriteAsyncCore.>d__5.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.IO.WindowsRuntimeStorageExtensions..<OpenStreamForWriteAsyncCore>d__5.MoveNext()

--- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at MyApp.IO.File.<CreateAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---

I am unable to recreate the issue myself so suspect its a threading issue but I'm completely at a loss as to how OpenStreamForWriteAsyncCore can throw this exception if the line before succeeds. Any suggestions what I may be doing wrong?

Upvotes: 1

Views: 301

Answers (1)

Archana
Archana

Reputation: 3221

This also might be possible-> thread 1 creates. Thread 2 recreates. Thread 1 tries to open the file but it is replaced. So exception throws. You have to do syncronously. Use lock to create and to do file operation or use semaphore to do file operation then release it when operation is done.

So better solution is to do it synchronously. Either use lock or semaphore. Here post the solution with semaphore.

SemaphoreSlim semaphore = new SemaphoreSlim(1);

public static async Task<Stream> CreateAsync(string path)
{
    StorageFile file;
    try
    {
        await semaphore.WaitAsync();
        StorageFolder folder = await Directory.GetFolderAsync(Path.GetDirectoryName(path));
        file= await folder.CreateFileAsync(Path.GetFileName(path), CreationCollisionOption.ReplaceExisting);
    }
    finally
    {
        semaphore.Release();
        return await file.OpenStreamForWriteAsync();
    }
}

Upvotes: 0

Related Questions