Page 1 of 1

ImageOutput in threads

Posted: Fri Apr 07, 2006 7:32 am
by Hugo
If I use StartDrawing(ImageOutput(#Image3)) in a tread and 'create threadsave executable' is activated, the debugger shows the error message: The specified output is NULL.

The reason for this is that ImageOutput(#Image3) returns 0.

It works without any problems when I disable 'create threadsave executable'.

So at the moment it's not possible for me to use 2D drawings to an image inside a thread.

Code: Select all

#WindowMain    =  1
#Image3        =  3
#ImageGadget   = 22

Global gBY_Exit.b
;Global gMX_Image3.l

Procedure MainThread( wert )
  
  ;LockMutex( gMX_Image3 )
  Debug "2. ImageOutput: " + Str( ImageOutput( #Image3 ) )
  ;UnlockMutex( gMX_Image3 )
   
  Repeat
    Delay(10)
  ForEver
  
EndProcedure


If OpenWindow( #WindowMain, 100, 100, 500, 400, "Test", #PB_Window_SizeGadget | #PB_Window_SystemMenu )

  CreateImage( #Image3, 200, 200 )
  ;gMX_Image3 = CreateMutex()
  
  If CreateGadgetList( WindowID( #WindowMain ) )
     ImageGadget( #ImageGadget, 20, 20, 200, 200, ImageID( #Image3 ) ) 
     
     ;LockMutex( gMX_Image3 )
     Debug "1. ImageOutput: " + Str( ImageOutput( #Image3 ) )
     ;UnlockMutex( gMX_Image3 )
        
     CreateThread( @MainThread(), 0 )
     
     Repeat
       Select WaitWindowEvent()
         Case #PB_Event_CloseWindow  : gBY_Exit = #True
       EndSelect
        
     Until gBY_Exit
        
  EndIf
  
EndIf

Posted: Fri Apr 07, 2006 10:27 am
by netmaestro
Threadsafety means image #s are maintained separately between main program and thread. You can reuse #image3 in your thread, even set it to a different image if you want. All you have to remember is that images created in the main program belong to the main program, and if you want to access them in a safe thread, you have to initialize them there, too. It's for all intents and purposes a separate program. It's a good thing, not a bug!

Posted: Fri Apr 07, 2006 12:36 pm
by Hugo
Ok, if this is the case, how can I initialize the image in the thread so I can access it form both the main program and the thread?

One other point here is that IsImage(#Image3) gives true back in the tread.

Posted: Fri Apr 07, 2006 12:49 pm
by Fred
I think it's a bug, i will take a closer look.

Posted: Fri Apr 07, 2006 1:59 pm
by Fred
My bad, you can't access to the same image in 2 differents threads. It's possible to draw to 2 differents images tough.

Posted: Fri Apr 07, 2006 2:51 pm
by freak
The problem in your code is that ImageOutput() cannot be used on its own.
You have to use it together with StartDrawing() and call the proper StopDrawing()
again before you can use the image again with StartDrawing()
Otherwise the image is not properly released from the device context used
for the drawing and it cannot be reused in another thread.


This works just fine:

Code: Select all

#WindowMain    =  1
#Image3        =  3
#ImageGadget   = 22

Global gBY_Exit.b
;Global gMX_Image3.l

Procedure MainThread( wert )
 
   If StartDrawing(ImageOutput(#Image3))
     Debug "2: OK"
     
     Line(0, 0, 200, 200, $FFFFFF)     ; test the drawing   
     StopDrawing()
     
     SetGadgetState(#ImageGadget, ImageID(#Image3)) ; update the gadget
   Else
     Debug "2: FAILED"
   EndIf  
   
  Repeat
    Delay(10)
  ForEver
 
EndProcedure


If OpenWindow( #WindowMain, 100, 100, 500, 400, "Test", #PB_Window_SizeGadget | #PB_Window_SystemMenu )

  CreateImage( #Image3, 200, 200 )
  ;gMX_Image3 = CreateMutex()
 
  If CreateGadgetList( WindowID( #WindowMain ) )
     ImageGadget( #ImageGadget, 20, 20, 200, 200, ImageID( #Image3 ) )
     
     If StartDrawing(ImageOutput(#Image3))
       Debug "1: OK"
       StopDrawing()
     Else
       Debug "1: FAILED"
     EndIf
     
     CreateThread( @MainThread(), 0 )
     
     Repeat
       Select WaitWindowEvent()
         Case #PB_Event_CloseWindow  : gBY_Exit = #True
       EndSelect
       
     Until gBY_Exit
       
  EndIf
 
EndIf