Page 1 of 2

[solved] GetGadgetText() problem inside a thread

Posted: Sat Apr 16, 2011 10:50 am
by infratec
Hi,

I created a program with threads.
Inside one thread I use GetGadgetText().
Only the main program has an event loop.

Now when I try to wait for the end of the thread inside of my main event loop with

Code: Select all

While IsThread() : wend
the program is blocked.
I discovered that GetGadgetText() is guilty.

To avoid the blocking I'm using now

Code: Select all

While IsThread() : WaitWindowEvent(1) : Wend
It works.

Is there a better solution?
Or where in the help is written that GetGadgetText() is only working when WindowEvent() is called?

Bernd

Re: GetGadgetText() problem inside a thread

Posted: Sat Apr 16, 2011 11:58 am
by c4s
Maybe WaitThread() or While IsThread() : Delay(10) : Wend works?

Re: GetGadgetText() problem inside a thread

Posted: Sat Apr 16, 2011 11:58 am
by infratec
A small example

Code: Select all

Global StartTime

Procedure TestThread(Value)
  
  StartTime = ElapsedMilliseconds()
  While ElapsedMilliseconds() - StartTime < 10000
    Debug 10000 - (ElapsedMilliseconds() - StartTime)
    Text$ = GetGadgetText(0)
  Wend
  
EndProcedure
  

OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ButtonGadget(0, 10, 10, 80, 20, "Start Thread")
ButtonGadget(1, 10, 40, 80, 20, "End Thread")

Exit = #False
Repeat
  
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Thread = CreateThread(@TestThread(), 0)
        Case 1
          StartTime = ElapsedMilliseconds() - 9950
          While IsThread(Thread) : Wend
;          While IsThread(Thread) : WaitWindowEvent(1) : Wend
          Debug "End !"
      EndSelect
    Case #PB_Event_CloseWindow
      Exit = #True
  EndSelect
      
Until Exit
If you press 'Start' you have 10 seconds time to 'End' the thread.
It is blocked.
To make it work, you have to comment the first while and discomment the second one.

Bernd

Re: GetGadgetText() problem inside a thread

Posted: Sat Apr 16, 2011 11:59 am
by infratec
c4s wrote:Maybe WaitThread() or While IsThread() : Delay(10) : Wend works?
Delay changes nothing :cry:
I already tested this.

I'll test WaitThread().

It is also not working (as expected).
Because the problem has nothing todo with the Thread-Functions.

Bernd

Re: GetGadgetText() problem inside a thread

Posted: Sat Apr 16, 2011 12:17 pm
by ts-soft

Code: Select all

Global StartTime

Procedure TestThread(Value)
 
  StartTime = ElapsedMilliseconds()
  While ElapsedMilliseconds() - StartTime < 10000
    Debug 10000 - (ElapsedMilliseconds() - StartTime)
    Text$ = GetGadgetText(0)
  Wend
 
EndProcedure
 

OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ButtonGadget(0, 10, 10, 80, 20, "Start Thread")
ButtonGadget(1, 10, 40, 80, 20, "End Thread")

Exit = #False
Repeat
 
  Event = WaitWindowEvent()
 
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Thread = CreateThread(@TestThread(), 0)
          AddWindowTimer(0, 1, 50)
        Case 1
          StartTime = ElapsedMilliseconds() - 9950
          Debug "End !"
      EndSelect
    Case #PB_Event_Timer
      If Not IsThread(Thread)
         RemoveWindowTimer(0, 1)
        Debug "End !"
      EndIf
    Case #PB_Event_CloseWindow
      Exit = #True
  EndSelect
     
Until Exit 

Re: GetGadgetText() problem inside a thread

Posted: Sat Apr 16, 2011 1:01 pm
by infratec
Hi,

yes, that's a 'safer' solution.
Thanks :!:

But...

It's horrible to implement in my program.
I'll give it a try.

Bernd

Re: GetGadgetText() problem inside a thread

Posted: Sun Apr 17, 2011 9:22 pm
by netmaestro
Your thread has no delay and so it's hogging the whole cpu. This is your main problem. There should be a Delay(1) in your While..Wend loop in the thread.

Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 7:28 am
by infratec
netmaestro wrote:Your thread has no delay and so it's hogging the whole cpu. This is your main problem. There should be a Delay(1) in your While..Wend loop in the thread.
Hi,

no, this is not my main problem :!:

I know that, but it changes nothing in the behaviour.
Even with a Delay(100), because it has nothing todo with the problem I described.

So it was not very helpfull.

But thanks anyway, maybe this hint is usefull for someone else.

Bernd

Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 11:45 am
by Vera
Hello infratec

I added to the while : wend loop: Delay(100)

and enhanced: Event = WaitWindowEvent(10)

and using : While IsThread(Thread) : Wend

This way I can immediately interrupt the thread anytime by stop-command or exit the app.
Just an idea and sorry in case I missed the point.

greetings ~ Vera

Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 11:59 am
by infratec
Hi Vera,

I don't know If I understand you correct.

I use now:

Code: Select all

Global StartTime

Procedure TestThread(Value)
 
  StartTime = ElapsedMilliseconds()
  While ElapsedMilliseconds() - StartTime < 10000
    Debug 10000 - (ElapsedMilliseconds() - StartTime)
    Text$ = GetGadgetText(0)
    Delay(100)
  Wend
 
EndProcedure
 

OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ButtonGadget(0, 10, 10, 80, 20, "Start Thread")
ButtonGadget(1, 10, 40, 80, 20, "End Thread")

Exit = #False
Repeat
 
  Event = WaitWindowEvent(10)
 
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Thread = CreateThread(@TestThread(), 0)
        Case 1
          StartTime = ElapsedMilliseconds() - 9950
          While IsThread(Thread) : Wend
;          While IsThread(Thread) : WaitWindowEvent(1) : Wend
          Debug "End !"
      EndSelect
    Case #PB_Event_CloseWindow
      Exit = #True
  EndSelect
     
Until Exit
But it still hangs.

The problem is still the same:

without calling WindowEvent() a GetGadgetText() stucks.

Bernd

Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 12:15 pm
by Vera
Yes, that's how I meant it.

But I don't get what hangs and why GetGadgetText() should be the cause that blocks your programm. Also a Debug Text$ (inside the thread) will be performed.

Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 12:25 pm
by infratec
Hi Vera,

I use Windows XP 32bit and PB 4.51.

When I press 'Start Thread' and I see the running down debug time,
and I press than 'Stop Thread' it hangs...

Ok, with your modifications, it can happen that it works.
But if you try it several times you get to a point where it hangs.

Test it.

Why:
When you press 'End Thread' and the thread is inside the Delay() it works.
But when it process the GetGadgetText() it happens.
So I can reduce the probability when I increase the delaytime, but that's not a fix :cry:

Bernd

Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 5:00 pm
by breeze4me
Try this.
If the message processing is blocked, the variable(Text$) is empty, but even then, the thread will not be hung.

Code: Select all

Global StartTime

Procedure TestThread(Value)
  Protected Text${256}, result
  
  StartTime = ElapsedMilliseconds()
  While ElapsedMilliseconds() - StartTime < 10000
    Debug 10000 - (ElapsedMilliseconds() - StartTime)
    ;Text$ = GetGadgetText(0)
    SendMessageTimeout_(GadgetID(0), #WM_GETTEXT, 256, @Text$, #SMTO_NORMAL, 800, @result)
    Debug Text$
    Text$ = ""
    Delay(100)
  Wend

EndProcedure


OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ButtonGadget(0, 10, 10, 80, 20, "Start Thread")
ButtonGadget(1, 10, 40, 80, 20, "End Thread")

Exit = #False
Repeat

  Event = WaitWindowEvent(10)

  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Thread = CreateThread(@TestThread(), 0)
        Case 1
          StartTime = ElapsedMilliseconds() - 9950
          While IsThread(Thread) : Wend
;          While IsThread(Thread) : WaitWindowEvent(1) : Wend
          Debug "End !"
      EndSelect
    Case #PB_Event_CloseWindow
      Exit = #True
  EndSelect
     
Until Exit

Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 5:52 pm
by RASHAD
Hi Bernd

Code: Select all

Global StartTime

Procedure TestThread(Value)
 
  StartTime = ElapsedMilliseconds()
    
  While (ElapsedMilliseconds() - StartTime) < 10000
    Debug 10000 - (ElapsedMilliseconds() - StartTime)        
    Text$ = GetGadgetText(0)
  Wend
 
EndProcedure
 

OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

ButtonGadget(0, 10, 10, 80, 20, "Start Thread")
ButtonGadget(1, 10, 40, 80, 20, "End Thread")

Exit = #False
Repeat
 
  Event = WaitWindowEvent()
 
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          If IsThread(Thread) = 0
            Thread = CreateThread(@TestThread(), 15)
          EndIf
        Case 1
          If IsThread(Thread)
            WaitThread(Thread,25)   ;Tested with Win 7 x64
            KillThread(Thread)
          EndIf
          ;StartTime = ElapsedMilliseconds() - 9950
          ;While IsThread(Thread) : Wend
;          While IsThread(Thread) : WaitWindowEvent(1) : Wend
          Debug "End !"
      EndSelect
    Case #PB_Event_CloseWindow
      Exit = #True
  EndSelect
     
Until Exit


Re: GetGadgetText() problem inside a thread

Posted: Mon Apr 18, 2011 8:39 pm
by infratec
@breeze4me

I think: the best solution so far
Only one disadvantage: It uses API stuff.
(But I didn't tetsted yet if it is the same behaviour in Linux)

@RASHAD

The brutal way of life :mrgreen:
A bit better:

Code: Select all

if WaitThread(Thread, 25) = 0
 KillThread(Thread)
endif
But I'm not sure if I can do this, because in my 'real' thread I do some serial stuff,
and I have to leave my buffers in a clean state. That's not possible with KillThread().


Best regards and thanks to all,

Bernd