Page 1 of 1

Why is Thread so slow?

Posted: Thu Jul 02, 2009 8:11 pm
by Polly
Can anybody pls explain me why the thread in the following example is so slow compared to directly executing it:

Code: Select all

If OpenWindow(0, 216, 0, 602, 302, "PureLVSORT Test",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
   ListIconGadget(0, 5, 5, 590, 285, "String", 110)
   AddGadgetColumn(0, 1, "Numeric", 110)
   AddGadgetColumn(0, 2, "Float", 110)
   AddGadgetColumn(0, 3, "DateDDMMYYYY", 120)
   AddGadgetColumn(0, 4, "DateMMDDYYYY", 120)
   For i=1 To 500
      AddGadgetItem(0, -1, "ABCDE" + Chr(10) + "514" + Chr(10) + "0.9" + Chr(10) + "31/12/2004" + Chr(10) + "12/31/2004")
   Next
EndIf

Global start0=ElapsedMilliseconds()

Procedure test(x)
    n=CountGadgetItems(0)-1
    For i=0 To n
       For j=0 To 4
          out$+GetGadgetItemText(0,i,0)+#TAB$
       Next
       out$+GetGadgetItemText(0,i,0)+#CRLF$
       start1=ElapsedMilliseconds()
       Debug start1-start0
       start0=start1
    Next
    Debug Len(out$)
EndProcedure

Repeat
  Event = WaitWindowEvent()
  If event=#PB_Event_Gadget   ; just click
;    test(0)    ; 100x faster!
    t=CreateThread(@test(),0)
    While IsThread(t)
       ev=WindowEvent()  ; if this is removed thread doesn't work at all
       If Not ev: Delay(10) : EndIf
    Wend 
  EndIf
Until Event = #PB_Event_CloseWindow
Also strange that it requires the message queue whilst during direct run no msg handling is in place.

PB 4.31/XP

Posted: Thu Jul 02, 2009 8:26 pm
by Kaeru Gaman
you should not seperate window handling on several threads.

all access to window objects should be placed within the same thread the concerning window is created and the eventloop is handled.

Posted: Thu Jul 02, 2009 9:49 pm
by helpy
Try this:

Code: Select all

EnableExplicit

Define i, hThread, Event

If OpenWindow(0, 216, 0, 602, 302, "PureLVSORT Test",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
  ListIconGadget(0, 5, 5, 590, 285, "String", 110)
  AddGadgetColumn(0, 1, "Numeric", 110)
  AddGadgetColumn(0, 2, "Float", 110)
  AddGadgetColumn(0, 3, "DateDDMMYYYY", 120)
  AddGadgetColumn(0, 4, "DateMMDDYYYY", 120)
  For i=1 To 500
    AddGadgetItem(0, -1, "ABCDE" + Chr(10) + "514" + Chr(10) + "0.9" + Chr(10) + "31/12/2004" + Chr(10) + "12/31/2004")
  Next
EndIf

Procedure test( x )
  Protected start0, start1, n, i, j, out.s
  start0 = ElapsedMilliseconds()
  n = CountGadgetItems(0)-1
  For i = 0 To n
    For j = 0 To 4
      out + GetGadgetItemText( 0, i, 0 ) + #TAB$
    Next
    out + GetGadgetItemText( 0, i, 0 ) + #CRLF$
    start1 = ElapsedMilliseconds()
    Debug start1 - start0
    start0 = start1
  Next
  Debug "Length: " + Str( Len(out) )
EndProcedure

Repeat
  Event = WaitWindowEvent()
  If event=#PB_Event_Gadget   ; just click
    ; do not start new thread, if it is still running
    If Not IsThread( hThread )
      hThread = CreateThread( @test(), 0 )
    EndIf
  EndIf
Until Event = #PB_Event_CloseWindow
The problem was:

Code: Select all

    While IsThread(t)
       ev=WindowEvent()  ; if this is removed thread doesn't work at all
       If Not ev: Delay(10) : EndIf
    Wend
1. With this Loop (especially Delay(1)) you slow down the message loop and therfore also the message handling!

2. In the thread you call CountGadgetItems and GetGadgetItem! These calls send messages from the running thread to the main thread (where the messagehandling will take place). And only if the messagehandling can do its job the thread will get the answer! If you wait for the end of the thread (with While IsThread()) then the message loop will not get any message except you put the ev=WindowEvent() in the Wait-Loop.

You do not need to wait for the end of the thread ... let the thread do its thing, until its finished ... and let the message handling loop do its thing without waiting for the end of the thread.

cu, helpy

Posted: Thu Jul 02, 2009 10:02 pm
by helpy
another thing:

Code: Select all

  n = CountGadgetItems(0)-1
  For i = 0 To n
    For j = 0 To 4
      out + GetGadgetItemText( 0, i, 0 ) + #TAB$
    Next
    out + GetGadgetItemText( 0, i, 0 ) + #CRLF$
  Next 
It is very slow to use a lot of these Gadget commands to fill a string. ... It would be much faster, if you store all the data (which is also displayed in the ListIconGadget) in an appropriate array. If you fill the string from the array data the routine would be much faster!

cu, helpy

Posted: Thu Jul 02, 2009 10:38 pm
by Polly
Thanks helpy for your answer, but that doesn't solve the problem. The issue is that the main thread is able to do something apart from just waiting for an event - without slowing down the second thread terribly.

But thinking about your suggestion I found another solution. Instead of doing:

Code: Select all

While IsThread(t)
       ev=WindowEvent() 
       If Not ev: Delay(10) : EndIf
Wend
I just need to do:

Code: Select all

While IsThread(t)
       ev=WaitWindowEvent(10) 
      ; do something 
Wend
Then the main thread is at least able to do something or just wait for the termination of the thread after some event w/o slow-down.