The problem is that after Window_OnKeyPressed returns, SFML.Net is still inside its internal call to window.pollEvent (triggered by _window.DispatchEvents()). But since you disposed the window, the next internal call that accesses it fails.
You shouldn't explicitly dispose the window instance, just let the GC do its job. Calling Close() is all you have to do.
Sorry, but I don't agree, according to the good practice, each object which is inherited from IDisposable, should be explicitly disposed. Otherwise it may cause memory leaks. If you don't do it, you will get a lot of warnings from code analyzing tools (suh as fxcop, resharper, etc).
It especially important for the objects which implementing finalizer. Such objects (with finalizer) will be marked as 2'nd generation object which actually never collected by the GC (except for the specific conditions, such as low memory, etc). GC will not touch such objects.
This is why adding finalizer to the object is a bad practice. Because such objects will be marked as 2'nd generation object and it will prevent GC to manage memory effectively, because GC actually will not work with such objects and it will consume a lot of memory.
GC is not intended to work effectively with objects which implementing finalizer. Such objects looks like hell for GC.
By the way, I've found a solution on how to avoid memory leaks on toggle window/fullscreen.
It works in the following way:
1) add two fields to store window instance: _window and _windowCache
2) On startup initialize _window in the usual way so it will works in windowed mode
3) When user requests fullscreen:
a) unsubscribe all events from _window
b) _window.SetVisible(false)
c) if _windowCache already initialized, just swap _window and _windowCache. Otherwise initialize fullscreen instance, assign it to _windowCache, and then swap _window and _windowCache.
d) resubscibe events for _window
e) _window.SetVisible(true)
So the application will hold two window instances - the first for windowed mode and the second for fullscreen mode. The second window just hidden and is not used. But, when user requests change, you just swap instances and continue to work.
Some kind of "Hot Swap" pattern for window
As a bouns it will provide extremely fast windowed/fullscreen switch with no artefacts. It works really good
It will take some time on the first switch (for the new window initialization). But the next switch will works just on the fly.Of course you can initialize both instances on startup, but it will cause a little longer startup time.
As a second bonus you don't need to store window position and size to restore it after switch back from fullscreen mode (I encountered such problem when used close window and create new one).
PS:
2Laurent: your approach for game loop (with separate window object) is really cool, I just used it for a small Direct2D prototype and I needs to say it's really cool, because it's very simple and extensible - the best implementation that I seen before - nice job!