Scott
Scott

Reputation: 1021

UWP StorageFile file in use by another process errors

The data for my app is stored in local JSON. I was originally storing it as an string app setting, but that doesn't offer enough space. So, I'm updating my app to read/write from a JSON file in local storage.

My app reads and writes the JSON at various times as a user interacts with my app and I'm getting this error a lot when reading or writing to the file:

System.IO.FileLoadException: 'The process cannot access the file because it is being used by another process.'

Here are the methods involved:

    private static async Task<StorageFile> GetOrCreateJsonFile()
    {
        bool test = File.Exists(ApplicationData.Current.LocalFolder.Path + @"\" + jsonFileName);

        if(test)
            return await ApplicationData.Current.LocalFolder.GetFileAsync(jsonFileName);
        else
            return await ApplicationData.Current.LocalFolder.CreateFileAsync(jsonFileName);

    }


    private static async void StoreJsonFile(string json)
    {
        StorageFile jsonFile = await GetOrCreateJsonFile();
        await FileIO.WriteTextAsync(jsonFile, json);
    }

    private static async Task<string> GetJsonFile()
    {
        StorageFile jsonFile = await GetOrCreateJsonFile();
        return await FileIO.ReadTextAsync(jsonFile);
    }

Sometimes the error is on the WriteTextAsync, sometimes the ReadTextAsync. There doesn't seem to be a specific point where the error occurs, just seems to happen randomly. Please let me know if there's some other way to do this to avoid the errors.

Upvotes: 3

Views: 1468

Answers (1)

Martin Zikmund
Martin Zikmund

Reputation: 39102

The problem is in your StoreJsonFile method. It is marked as async void, which is a bad practice. When you call this method and it reaches the first IO-bound async call (in this case FileIO.WriteTextAsync), it will just end the execution and will not wait for the IO operation to finish. This is a problem, because the file may be in use (or it may not even be created yet) when you call the GetJsonFile. Furthermore - the write may not start when the ReadTextAsync has already started executing because the system ran that method first. That explains why you may see the exception in both methods.

The solution is quite simple - don't use async void and use async Task instead:

private static async Task StoreJsonFile(string json)
{
    StorageFile jsonFile = await GetOrCreateJsonFile();
    await FileIO.WriteTextAsync(jsonFile, json);
}

And when you call your methods, always remember to use await to ensure the execution will continue after the IO operation finishes so that there is not a risk of race conditions.

Upvotes: 5

Related Questions