
System.Threading.Timer generating random OpenGL errors
Posted Monday, 8 August, 2011 - 15:57 by SPGardebiter inHello. I'm trying to learn hwo to use OpenTK with VB.NET and I run into trouble.
I'm trying to use a Timer instead of a GameWindow but it produces random errors, sometimes I run into a AccessViolation and sometimes I can't swap the buffers. At the moment I'm using the newest version of OpenTK together with Visual Basic .NET 2005.
Windows.Forms.Timer works but System.Threading.Timer doesn't.
This is my code:
Imports OpenTK Imports OpenTK.Graphics.OpenGL Imports OpenTK.Audio Imports OpenTK.Audio.OpenAL Imports OpenTK.Input Imports OpenTK.GLControl Imports OpenTK.Platform Imports System.Drawing Imports System.IO Imports System.Threading Public Class frm_main Public Loaded As Boolean Public Counter As New Stopwatch() Public Timer As System.Threading.Timer Private Sub GLC_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles GLC.Load GL.ShadeModel(ShadingModel.Flat) GL.ClearColor(Color.Black) GL.MatrixMode(MatrixMode.Projection) ' Projection Matrix GL.LoadIdentity() ' Reset GL.Viewport(0, 0, GLC.Width, GLC.Height) GL.Ortho(0, 640, 0, 480, 0, 256) Timer = New System.Threading.Timer(AddressOf Tick, Nothing, 1000, 2000) End Sub Private Sub GLC_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles GLC.Resize GL.MatrixMode(MatrixMode.Projection) ' Projection Matrix GL.LoadIdentity() ' Reset GL.MatrixMode(MatrixMode.Modelview) ' Modelview Matrix GL.LoadIdentity() ' Reset GL.Viewport(0, 0, GLC.Width, GLC.Height) End Sub Private Sub Tick(ByVal sender As System.Object) Counter.Stop() Me.Text = "Sturmfaust Engine .NET (" & Counter.ElapsedMilliseconds.ToString & ")" Counter.Reset() Counter.Start() GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) GL.LoadIdentity() GLC.SwapBuffers() End Sub End Class
Anyone got an idea?


Comments
Re: System.Threading.Timer generating random OpenGL errors
System.Threading.Timer runs on a separate thread that does not have access to an OpenGL context. You can only use OpenGL from a thread with an OpenGL context, see the documentation for more details.
In short, choose which thread will be issuing OpenGL commands (the main thread or the Timer thread) and call MakeCurrent() on that thread. Check the aforementioned documentation for example code.
Re: System.Threading.Timer generating random OpenGL errors
Timers run on worker threads in .Net, the resize and Paint methods run on the message pump thread, directly accessing GL on a timer thread is generally not safe without understanding multithreading in OpenGL.
You have a couple of options, the "right" way to do it is just to call Invalidate in the timer and leave the render code in the PAINT/Render function, windows will post a message back to the primary thread and it will do the rendering.
You could post your own custom message, but that's a lot of work for no benefit.
And the last is you could use Invoke to call your rendering code this posts a message back to the primary thread, and waits until it finishes executing the "Invoked" function before continuing, generally I would consider this a last resort.