opentk / GLWpfControl

A fast native control for OpenTK 4.x + 3.x on WPF.
MIT License
196 stars 49 forks source link

Error When Disposing GlWpfControl on a Thread Other Than Main #132

Open anose001 opened 3 months ago

anose001 commented 3 months ago

The view containing my GlWpfControl throws the error

OpenTK.Windowing.GraphicsLibraryFramework.GLFWException: 'You can only dispose windows on the main thread. The window needs to be disposed as it cannot safely be disposed in the finalizer.'

in DXGLContext.cs at GlfwWindow?.Dispose(); in the Dispose() method when navigating views in my application. I am not closing any windows and my application keeps running.

I tried to keep it on the main thread with a Dispatcher call explicitly calling out the Dispose() method on MyGlWpfControl.

    protected void OnClosed(object o, RoutedEventArgs e)
    {
        Application.Current.Dispatcher.Invoke(() =>
        {
            MyGlWpfControl.Render -= OnRender;
            MyGlWpfControl.Dispose();   
        });
    }

but to no effect. Removing the OnClosed() method gives the same outcome.

Once the view is changed I believe that the garbage collector frees the resource on some thread other than the main thread.

I assume there is a good reason to dispose the window on the main thread but don't really know what that is right now.

What is the recommended approach to dispose a GlWpfControl while my application is running?

NogginBops commented 3 months ago

You need to dispose the control on a thread that has the OpenGL context associated with the control current. Otherwise opengl functions will fail (there is also glfw reasons on macOS (I think) where you need to be on the main thread). You can't have a context current on two threads at once, and because the render thread is likely using the context a lot of the time and syncing with it is hard, so it's easiest to keep it all on the main thread.

But it's possible that we have a bug where is using multiple controls will cause the wrong OpenGL context to be current when disposing, and I think we don't make sure the context is current when disposing, so there is a possible bug there.

simfero commented 2 months ago

@anose001 were you able to find the workaround for the disposal issue? I'm running into the same issue.

anose001 commented 2 months ago

@simfero, I moved forward to the next part of the project and I am not sure I remember. Did the latest GlWpfConotrol release 4.3.2 fix the crash issue for you? Are you manually disposing off the control?

simfero commented 2 months ago

@anose001 I get this exception with 4.3.2. I have tried manually disposing and I get the same exception.

NogginBops commented 2 months ago

@simfero are you disposing on the main thread?

simfero commented 2 months ago

@NogginBops I checked thread ids and it's not disposing on the main thread.

NogginBops commented 2 months ago

You need to call dispose on the main thread

simfero commented 2 months ago

@NogginBops It's being disposed on GE Finalizer Thread.

However, everything works as expected with this branch: https://github.com/opentk/GLWpfControl/pull/135

NogginBops commented 2 months ago

It's being disposed on GE Finalizer Thread.

You can't rely on the finalizer to dispose of the control, you are going to have to call dispose yourself from the main thread. I'm not sure there is anything in #135 that would allow you to dispose the control from the finalizer thread, so not sure what that is about.