Reputation: 38106
A common approach to saving and loading of user / application settings in a GUI application looks like this:
private void FormMain_Load(object sender, EventArgs e)
{
m_foo = Properties.Settings.Default.Foo;
}
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.Save();
}
At first glance, this looks reasonable. However, once you consider what actually transpires inside the save and (implicit) load operations, namely disk I/O, it appears a bit suspect. Doesn't it stand against the principle of avoiding potentially long running operations in general and especially I/O on the GUI thread?
I realize that in the vast majority of cases we're talking about very small files located on a local hard drive, but I can come up with scenarios where the operation would take some time to complete if I really wanted to (disk was put to sleep, disk is under stress, disk is actually network storage, etc).
Also, it's not clear what I should do about it. Startup is easy enough to handle, disabling the GUI while the settings are loading asynchronously. But what about the close event? Sure, I could cancel the event, save asynchronously, and then close it myself but it gets a little messy as I need to take care of cases where the user tries to close it again before I finished saving (so I don't initiate another save, or exit while in the middle of saving etc). And I'm not sure it can even be done (at least simply) in other frameworks, say GTK# where the OnDeleteEvent is typically used when it's too late. I suppose I could fire a foreground thread and save it there, but then the user might think the application is closed and run it again before the settings were actually saved (and there could be other consequences for having multiple instances of it alive regardless).
Should I be worried about such scenarios or am I overthinking it?
Upvotes: 2
Views: 191
Reputation: 1897
I think you're forgetting the "why" of the general rule (which is the danger with all general rules). The "why" behind "the principle of avoiding potentially long running operations in general and especially I/O on the GUI thread" is to maintain responsiveness (low latency) in the user interaction. If you do long-running work in the GUI thread then your GUI won't refresh as quickly.
What user interaction is needed as the application is loading (before it's ready to run), or as it is closing (when it can no longer be interacted with)? There are scenarios when there is a legitimate answer (interacting with another window in this app, etc.), but this is a minority of the time.
Also, there are various buffers that can help mitigate any latency here. The file is likely read into a disk buffer before your app calls the read of the config (not necessarily). Disk output need only go to the nearest buffer before the app can close.
Upvotes: 2
Reputation: 941327
You are over-thinking it. Presumably based on the assumption that saving settings is slow. It is not in a Winforms app, you are not running this app on a mobile device. File writes are always cached by the file system cache, nothing but a memory-to-memory copy. They run at memory bus speeds, 5 gigbytes/sec at its slowest (old DDR2), more typically around 35 GB/sec.
After which the file system driver lazily writes the changes to disk, highly optimized to minimize the write head movement. Writes up to ~1 gigabyte can fit on modern machines, much more if it has enough RAM. An easy 6 orders of magnitude more than you'll ever need for a user.config file.
Any optimization that turns it into an async write cannot ever make the responsiveness of your app better than a millisecond, completely unobservable by a human. Also the reason why this isn't supported by System.Configuration. You don't have a real problem.
Upvotes: 5