Istrebitel's picture

What is the difference between OpenTK (nightly) using SDL2 or not using it?


I'm using OpenTK (nightly version). The following simple code:

SimpleWindow example = new SimpleWindow();
// no more references in the code exist of the "example" variable

Will show OpenGL window - and when it is closed, it will be properly closed (disappear from task bar in windows and so on) if NOT using SDL2.dll, but will stay visible (and in task bar) if using SDL2.dll. However, the following code:

using (SimpleWindow example = new SimpleWindow())

Will work both with and without SDL2.dll - the window properly closes and disappears.

What is the key difference here?

EDIT: I found a more grave difference.

Simple application, a form with one button, in the button code I do this:

using (SimpleWindow example = new SimpleWindow()) { example.Run(); }

Now, without SDL2.dll, I can do this all day - I can spawn however many windows I need (closing current one before opening another). However, with SDL2.dll, when I close a window, after a certain time passes, if I try to spawn another window, I get this when doing .Run():

A callback was made on a garbage collected delegate of type 'OpenTK!OpenTK.Platform.SDL2.EventFilter::Invoke'. 
This may cause application crashes, corruption and data loss. 
When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

Can this be avoided? Can I GC.KeepALive() something to prevent this from happening?


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Thanks for reporting these issues. Could you please file a bug (one per issue) at

The first issue is caused by not using GameWindow.Dispose(). This means that the GameWindow is finalized on a different thread than the thread it was created on. In the case of native WinAPI we know that we can destroy the window handle on a different thread. In the case of SDL, however, we don't, which leads to a resource leak.

I have raised this question in the SDL mailing list. The correct solution depends on their answer.

Rule of thumb: if a Dispose() method exists, it exists for a reason! The GC will take care of memory resources, but everything else is the responsibility of the programmer (file handles, sockets, window handles, render contexts, texture handles, etc etc)

Istrebitel's picture

Erm, one per issue? Based on what you said, isn't first one not an issue, but rather me failing to call Dispose immedaitely after Run?

Posted the second issue here

the Fiddler's picture

Thanks. The answer from the SDL devs is that SDL_DestroyWindow must only be called on the main thread, which means you need to use Dispose().

I will try to see if there is any reasonable workaround for GC.

Istrebitel's picture

I'm not sure I understand, so, is it possible to open multiple SDL windows in succession, without getting the error I'm getting? If so, how?

the Fiddler's picture

Yes, the second is now fixed in git master, with commit 48803bb4d6. As long as you call Dispose(), you should be able to open an indefinite amount of windows (please verify.)

If you don't call Dispose() you get the other issue you mentioned (the window does not close). I will try to find if there is a reasonable workaround that can be implemented inside OpenTK.

Istrebitel's picture

Well, I haven't tested for a very long time, but before it would bug out if I let window stay closed for about several seconds, right now I've waited for some minutes and it still lets me open new windows, so I guess, we can consider this fixed! Thanks, now my program is working completely :)

Istrebitel's picture

EDIT: Issue resolved (found out that if you hide cursor in the window, you have to return CursorVisible to true before Exit/Close of a GameWindow, otherwise next GameWindow will not properly grab focus and will not process mouse events, until you alt-tab out of it and into it)

the Fiddler's picture

Thanks for the detailed testing, this is now fixed in 75d4f3d