Daniel
Daniel

Reputation: 1114

How to save program state on program close using aync file operations

I am trying to save program state if user closes the program or initiates shutdown while program is still running but in this case the Task is not awaited and program terminates during writing settings leading to file corruption. How do I do it without creating an additional synchronous method for saving?

private async void Window_Closed(object sender, EventArgs e)
{
    await programState.Save();
}

//from programState class
private async Task Save()
{        
    var state = JsonConvert.SerializeObject(progState, Formatting.Indented);
    using (FileStream stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
    {
        using (var sw = new StreamWriter(stream))
            await sw.WriteAsync(state).ConfigureAwait(true);
    } 
}

Upvotes: 2

Views: 64

Answers (1)

TheGeneral
TheGeneral

Reputation: 81513

There is no need to use the streams async methods in this case, just use the regular StreamWriter.Write on a synchronous path (i.e don't use the async and await pattern).

However, if you really had a need to use the async and await pattern from an event like Window_Closed and it needed to be waited on (still knowing there is no good reason for it in this case), you will have to remove the async void on Window_Closed event; offload the work; then wait for it (not recommended)

private void Window_Closed(object sender, EventArgs e)
{
    Task.Run(() => programState.Save()).Wait();
}

Note : Running asynchronous code synchronously usually leads to deadlocks in UI frameworks because of the way the continuations work with the MessagePump and Dispatchers. In this case you are offloading the async work to the thread-pool and negating the deadlock via a sacrificial thread. In short, don't do it, just save to the stream synchronously

Upvotes: 1

Related Questions