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 |