Speed up filling ListiconGadget from thread?

Just starting out? Need help? Post your questions and find answers here.
novablue
Enthusiast
Enthusiast
Posts: 165
Joined: Sun Nov 27, 2016 6:38 am

Speed up filling ListiconGadget from thread?

Post by novablue »

I am filling a ListiconGadget with a lot of lines so i put it into a seperate thread to not lock up the program, hower this seems to significantly slow it down with thread safe on or off, i also notice that SetGadgetItemColor from a thread is very slow too.

My Times are 2000ms filling from thread and 400ms from the main, and with SetGadgetItemColor commented out i get 600ms from thread and 200ms from main.

is there any way to speed this up?

Code: Select all

Procedure.i Fill(Listicon.i) 
    SendMessage_(GadgetID(Listicon), #WM_SETREDRAW, 0, 0)
    For I = 0 To 5000 
        AddGadgetItem(Listicon, -1, "Test " + I)
        SetGadgetItemColor(Listicon, I, #PB_Gadget_BackColor, #Green) ; Comment out for speedup
    Next
    SendMessage_(GadgetID(Listicon), #WM_SETREDRAW, 1, 0)
EndProcedure

Define MainWindow.i = OpenWindow(#PB_Any, 0, 0, 500, 500, "MainWindow", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
Define Listicon.i   = ListIconGadget(#PB_Any, 0, 0, 500, 500, "Test", 480)

Timer.i  = ElapsedMilliseconds()
Thread.i = CreateThread(@Fill(), Listicon)
While (IsThread(Thread)) : WaitWindowEvent(10) : Wend
Debug ElapsedMilliseconds() - Timer

ClearGadgetItems(Listicon)

Timer.i = ElapsedMilliseconds()
SendMessage_(GadgetID(Listicon), #WM_SETREDRAW, 0, 0)
For I = 0 To 5000 
    AddGadgetItem(Listicon, -1, "Test " + I)
    SetGadgetItemColor(Listicon, I, #PB_Gadget_BackColor, #Green)
Next
SendMessage_(GadgetID(Listicon), #WM_SETREDRAW, 1, 0)
Debug ElapsedMilliseconds() - Timer

Repeat 
	WaitWindowEvent()
ForEver
User avatar
jacdelad
Addict
Addict
Posts: 1475
Joined: Wed Feb 03, 2021 12:46 pm
Location: Planet Riesa
Contact:

Re: Speed up filling ListiconGadget from thread?

Post by jacdelad »

SetGadgetItemColor is slow, yes.
On Windows: When starting the operation use

Code: Select all

SendMessage_(GadgetID(gadget),#WM_SETREDRAW,0,0)
and after finishing

Code: Select all

SendMessage_(GadgetID(gadget),#WM_SETREDRAW,1,0)
This temporarily disables redrawing and speeds it up a lot.
Another way is to use ownerdrawn listicongadgets. Search the forum, that's been posted somewhere.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Rinzwind
Enthusiast
Enthusiast
Posts: 638
Joined: Wed Mar 11, 2009 4:06 pm
Location: NL

Re: Speed up filling ListiconGadget from thread?

Post by Rinzwind »

Updating GUI from another thread is not advised in any language. Just FYI.
User avatar
mk-soft
Always Here
Always Here
Posts: 5393
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Speed up filling ListiconGadget from thread?

Post by mk-soft »

On Linux and MacOS is not possible to fill from Threads.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mrv2k
User
User
Posts: 51
Joined: Fri Jan 20, 2012 3:40 pm
Location: SE England
Contact:

Re: Speed up filling ListiconGadget from thread?

Post by mrv2k »

Try a virtual listicon. I can load 38000 items in 27ms. It does add some complications programatically that need to be worked around but it's worth it if you need speed.

Here's an example

Code: Select all

#ItemCount = 5000
#LVSICF_NOINVALIDATEALL = 1
#LVN_ODCACHEHINT = #LVN_FIRST - 13  
  
Global Dim myItems.s(#ItemCount)
  
Procedure WindowCallback(win, msg, wParam, lParam) ; <--------------------> Main Window Callbacks
  
  result = #PB_ProcessPureBasicEvents 
  Select msg 
    Case #WM_NOTIFY 
      *pnmh.NMHDR = lParam 
      *LVCDHeader.NMLVCUSTOMDRAW = lParam
      Select *LVCDHeader\nmcd\dwDrawStage
        Case #CDDS_PREPAINT
          ProcedureReturn #CDRF_NOTIFYITEMDRAW
        Case #CDDS_ITEMPREPAINT
          ; simple example - change text and background colors every other row
          Row = *LVCDHeader\nmcd\dwItemSpec
            *LVCDHeader\clrText = RGB(0, 0, 0)
            *LVCDHeader\clrTextBk = RGB(0, 255, 0)
          ProcedureReturn #CDRF_DODEFAULT
      EndSelect
      Select *pnmh\code 
        Case #LVN_ODCACHEHINT 
          result = 0 
        Case #LVN_GETDISPINFO
          *pnmlvdi.NMLVDISPINFO = lParam 
          If *pnmlvdi\item\mask & #LVIF_TEXT
            Item = *pnmlvdi\item\iItem
            Text$ = myItems(Item)
            *pnmlvdi\item\pszText = @Text$
          EndIf 
      EndSelect 
  EndSelect 
  ProcedureReturn result 
  
EndProcedure

Define MainWindow.i = OpenWindow(#PB_Any, 0, 0, 500, 500, "MainWindow", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered| #LVS_OWNERDATA)
Define Listicon.i   = ListIconGadget(#PB_Any, 0, 0, 500, 500, "Test", 480,#LVS_OWNERDATA)

SetWindowCallback(@WindowCallback()) 

Timer.i = ElapsedMilliseconds()

SendMessage_(GadgetID(Listicon), #WM_SETREDRAW, 0, 0)

SendMessage_(GadgetID(Listicon), #LVM_SETITEMCOUNT, #ItemCount, #LVSICF_NOINVALIDATEALL) 

For I = 0 To #ItemCount
  myItems(I)="test "+ Str(I)
Next

SendMessage_(GadgetID(Listicon), #WM_SETREDRAW, 1, 0)
RedrawWindow_(GadgetID(Listicon),#Null,#Null,#RDW_INVALIDATE)

Debug ElapsedMilliseconds() - Timer

Repeat 
	event=WaitWindowEvent()
Until event=#PB_Event_CloseWindow
Generates the list in 3ms with coloured items.

Rashad has a good bit of code here... viewtopic.php?f=12&t=76419
novablue
Enthusiast
Enthusiast
Posts: 165
Joined: Sun Nov 27, 2016 6:38 am

Re: Speed up filling ListiconGadget from thread?

Post by novablue »

Thank you all, i thought i was being smart by putting it into a thread and not lagging the main thread out but i will try a different approach. Virtual Listicon sounds interesting i am surprised nobody made an module for it yet for easier use? :lol:
Post Reply