Threaded Canvas Drawing
BlitzMax Forums/MaxGUI Module/Threaded Canvas Drawing
| ||
| Hey Everyone, I've been trying for too many hours now to figure out the best way to update a MaxGUI Canvas via another thread. So far I have managed to lock up my iMac 3 times, and have gotten no where. I've read on other topics that the GUI must be redrawn from the main thread (I'm assuming that is where the crashes are coming from). So if I can't update the canvas from another thread, how would I go about making the rest of the GUI not block when I click a button or drag a scroll bar? |
| ||
| Graphics actions (like drawing and flipping) can only be done from the main thread, this is a limitation of the graphics drivers/subsystem of the computer. Event commands should also only be handled from 1 thread as the bmax event que is not thread safe. Perhaps you can post an example of how/why you need to update from another thread. I have no problems have my draws handled I the main thread but Im not doing animations etc. So I don't need to redraw at a game speed... To be able to requests draws from a child thread I have a second event que that I manage, whenever the normal que progresses it dumps the thread safe que into the main que, however I have an odd program flow (I don't use waitevent() for example...) so that may not nesicarily work for you... |
| ||
Here is a sample of what I'm trying to achieve. I would like the spinning clock (or any other animation) to keep spinning while the user does GUI Actions. Clicking the button or holding the button down gives an example of what I would not like to happen.SuperStrict
'Import Needed Libraries
Framework brl.blitz
Import BRL.filesystem
Import BRL.Threads
Import brl.appstub
Import maxgui.drivers
Import brl.EventQueue
Import brl.max2d
Import brl.GLGraphics
Import brl.Graphics
Import BRL.Timer
Import BRL.GLMax2d
Import BRL.Max2d
Import BRL.Retro
'Global Variables
Global frmMain:TfrmMain = TfrmMain.Create()
Global graphicsTimer:TTimer=CreateTimer(60)
Global isRunning:Byte = True
'Loop the event Listener
Repeat
Local e:Int=WaitEvent()
HandleEvent(CurrentEvent)
Forever
'Handle and Event
Function HandleEvent(e:TEvent)
If isRunning
Select e.ID
Case EVENT_TIMERTICK
If e.source = GraphicsTimer
GraphicsUpdater(Null)
End If
Case EVENT_APPTERMINATE
Destroy()
End Select
End If
End Function
'End
Function Destroy()
IsRunning = False
End
End Function
'Update the Graphics, Ideally this would be done on another thread
Function GraphicsUpdater:Object(data:Object)
SetGraphics CanvasGraphics(frmMain.PreviewCanvas)
SetOrigin 160,90
SetLineWidth 5
Cls
Local t:Long=MilliSecs()
DrawLine 0,0,120*Cos(t),120*Sin(t)
DrawLine 0,0,80*Cos(t/60),80*Sin(t/60)
Flip
End Function
Type TfrmMain
Field Window:TGadget
Field isVisible:Byte
Field RawList:TGadget
Field RawLabel:TGadget
Field DisplayList:TGadget
Field PreviewCanvas:TGadget
Field AcceptButton:TGadget
Field DeclineButton:TGadget
Field SelectedItem:Int
Field SelectedGadget:Int
'Create the Main Window
Function Create:TfrmMain()
Local _frmMain:TfrmMain = New TfrmMain
_frmMain.Window = CreateWindow("Tabernacle SMS",10,10,900,700)
_frmMain.AcceptButton= CreateButton("A",410,300,50,25,_frmMain.Window)
_frmMain.PreviewCanvas = CreateCanvas(500,10,320,180,_frmMain.Window)
_frmMain.isVisible=True
Return _frmMain
End Function
End Type
|
| ||
| Unfortunately that's exactly what you can't do. Graphics commands have to be on the main thread. Try going about it another way, i.e. putting the other stuff that takes time on a child thread. and try to keep the main thread for just graphics updates, event que management, and other management tasks. If whatever you're going to draw is going to take a long time to calculate, perhaps you can split the draw from the calculation, maybe have a child thread running your calculations and split them from the draw process... Or if you're trying to make room for loading then do the loading in a child thread instead. Threading is PITA to work with, and has some inherent bugs on top of the added complexity of debugging your own code, on top of the extra steps you have to go through to make sure your own code is thread safe... on top of having to know what is thread safe to begin with... |
| ||
| I've posted some threading tutorials, perhaps they can be helpful http://www.blitzbasic.com/Community/posts.php?topic=91458 |