After a great deal of confusion around DisplayDevice.ChangeResolution() and DisplayDevice.RestoreResolution(), I managed to track down what I believe to be the source of my problem. I'm not sure if this is intended behavior, but it certainly seems like a bug.
I observed that RestoreResolution was not... restoring my resolution. Using Visual Studio's debugger, I noticed that ChangeResolution was correctly setting original_resolution, it would be null when RestoreResolution looked at it. But nothing seemed to be overwriting the field.
After looking around some more, I put a breakpoint on the WinDisplayDevice.RefreshDisplayDevices definition. This revealed that it was being called when the display resolution changed on my computer. The problem is that the method clears and rebuilds the list of available devices. The original DisplayDevice objects are no longer referenced by anything, and presumably are eaten by the GC. But those DisplayDevice objects still had important information, namely the original_resolution field!
This means that calling:
and later calling:
will not reference the same object if the device list has been rebuilt, and RestoreResolution will not work as expected!
As a workaround, I now create a reference to the default DisplayDevice in my main window class and call methods on it rather than DisplayDevice.Default.
Still, this seems like unexpected behavior to me, so I thought I would report it.