Hello,
I am writing an application that fills a listicon gadget with thousands of records..
I have a thread reading the database and updating the listicon in the main window.. that part works great.. the intention of doing this is so that if the user clicks anything on the window, the display/window doesn't freeze..
The problem is this.. I am also trying to add a progress bar that lets the user know how much farther there is to process..
so far.. I have a second thread that creates it's own child window that holds only the progressbar gadget. Does anyone have an example of how to do this..
What constitutes threadsafe?
Hi Blackorg,
I am probably not the person to answer this for you, but here is a snippet I have made up for you which I think may do the job.
This snippet simply opens & reads a text file which is then placed into a linked list with numbered lines & then added to a listicon gadget in the main window.
It was my 2nd effort, with the 1st failing to work when the compiler threadsafe switch option was enabled. ( Which is also the reason why I have used a control from the main loop to open & close the 2ndry window instead of directly from the thread. )
Maybe 1 of the guru's would like to check my code & fix as needed...
I have tried this code using Win Xp to load a text file containing 160,000 lines of text without fault.
( Just took a while to read all those lines )
I am probably not the person to answer this for you, but here is a snippet I have made up for you which I think may do the job.
This snippet simply opens & reads a text file which is then placed into a linked list with numbered lines & then added to a listicon gadget in the main window.
It was my 2nd effort, with the 1st failing to work when the compiler threadsafe switch option was enabled. ( Which is also the reason why I have used a control from the main loop to open & close the 2ndry window instead of directly from the thread. )
Maybe 1 of the guru's would like to check my code & fix as needed...
Code: Select all
; PureBasic Visual Designer v3.95 build 1485 (PB4Code)
Enumeration
#Window_0
#Window_1
#ListIcon_0
#Button_0
#Text_0
#ProgressBar_0
#File_0
EndEnumeration
Structure MyInfo
Line.l
String.s
EndStructure
Global NewList MyData.MyInfo() ;may as well give the thread something to do!!
Procedure Open_Window_0()
If OpenWindow(#Window_0, 258, 4, 600, 300, "New window ( 0 )", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
If CreateGadgetList(WindowID(#Window_0))
ListIconGadget(#ListIcon_0, 20, 15, 555, 215, "Line", 50, #PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect)
AddGadgetColumn(#ListIcon_0,1,"String",450)
ButtonGadget(#Button_0, 20, 250, 50, 20, "Select")
EndIf
EndIf
EndProcedure
Procedure Open_Window_1()
If OpenWindow(#Window_1, 236, 20, 326, 89, "New window ( 1 )", #PB_Window_TitleBar,WindowID(#Window_0) )
If CreateGadgetList(WindowID(#Window_1))
TextGadget(#Text_0, 15, 10, 295, 20, "", #PB_Text_Center | #PB_Text_Border)
ProgressBarGadget(#ProgressBar_0, 15, 50, 295, 20, 0, 100,#PB_ProgressBar_Smooth)
EndIf
EndIf
EndProcedure
Procedure Update(F$)
Shared Destroywindow.l
If ReadFile(#File_0,F$)
DisableGadget(#ListIcon_0,1)
DisableGadget(#Button_0,1)
SetGadgetText(#Text_0,"Deleting existing lists, please wait....")
Flen.f=Lof(#File_0)
ClearGadgetItemList(#ListIcon_0)
ClearList(MyData())
AddElement(MyData())
count=0
SetGadgetText(#Text_0,"Updating, please wait....")
Repeat
count+1
MyData()\Line=count
MyData()\String=ReadString(#File_0)
AddGadgetItem(#ListIcon_0,-1,"")
SetGadgetItemText(#ListIcon_0,count-1,Str(MyData()\Line),0)
SetGadgetItemText(#ListIcon_0,count-1,MyData()\String,1)
pos.f=Loc(#File_0)
mypos.l= pos/Flen*100
SetGadgetState(#ProgressBar_0,mypos)
AddElement(MyData())
Until Eof(#File_0)
CloseFile(#File_0)
DisableGadget(#ListIcon_0,0)
DisableGadget(#Button_0,0)
Destroywindow=1
EndIf
EndProcedure
Open_Window_0()
Repeat
Ev=WaitWindowEvent(10)
If Destroywindow
If IsWindow(#Window_1)
CloseWindow(#Window_1)
EndIf
Destroywindow=IsThread(MyThread)
EndIf
If Ev=#PB_Event_Gadget
Select EventGadget()
Case #Button_0
File$=OpenFileRequester("Select File","","Text (*.txt)|*.txt",0)
If File$
Open_Window_1()
Mythread=CreateThread(@Update(),File$)
EndIf
EndSelect
EndIf
If Ev=#PB_Event_CloseWindow
Select EventWindow()
Case #Window_0
Quit.b=#True
EndSelect
EndIf
Until Quit
End
( Just took a while to read all those lines )
- Kaeru Gaman
- Addict

- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
hi blackborg,
you need to know the total number of records before starting the load.
if that is not a fix value, you could calculate it by the total length
of the file devided by the length of one record.
from this you have the maximum for the ProgressBarGadget.
the minimum in this case should be zero.
communication between seperate threads could be handled over global variables.
in the load-thread you count a global counter up each loaded record.
in the ProgressBarGadget-thread you set the GadgetState according to this global counter.
note that the thread needs an own eventloop to display the update of the gadget properly.
also the opening of the window and the creating of the ProgressBarGadget
should be within this thread.
the eventloop may look like this:
the EndCondition also can be a Global Variable, that will be set to #True
by the Load-Thread when loading is finished.
the 100 lets the thread wait for 1/10sec between the updates of the progressbar.
in the first pass, Event is 0 because the 100ms ran out without an event.
so the progressbar is updated, and an event is created.
instandly in the second pass the update-event can be handled without
creating a new event, the updated progressbar is displayed.
next, the code will wait another 100ms.
hope it helped a bit....
you need to know the total number of records before starting the load.
if that is not a fix value, you could calculate it by the total length
of the file devided by the length of one record.
from this you have the maximum for the ProgressBarGadget.
the minimum in this case should be zero.
communication between seperate threads could be handled over global variables.
in the load-thread you count a global counter up each loaded record.
in the ProgressBarGadget-thread you set the GadgetState according to this global counter.
note that the thread needs an own eventloop to display the update of the gadget properly.
also the opening of the window and the creating of the ProgressBarGadget
should be within this thread.
the eventloop may look like this:
Code: Select all
Repeat
Event = WaitWindowEvent(100)
If Event = 0
SetGadgetState(#ProgressBar, GlobalCounter)
EndIf
Until EndConditionby the Load-Thread when loading is finished.
the 100 lets the thread wait for 1/10sec between the updates of the progressbar.
in the first pass, Event is 0 because the 100ms ran out without an event.
so the progressbar is updated, and an event is created.
instandly in the second pass the update-event can be handled without
creating a new event, the updated progressbar is displayed.
next, the code will wait another 100ms.
hope it helped a bit....
oh... and have a nice day.
code snippet
looks good.. crashes for me though with invalid memory access
- Kaeru Gaman
- Addict

- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
just needed an update for PB.. that resolved it..
but I really would like to know what functions need to be mutexed.. like, does assigning a string value to a variable in a thread need to be mutexed.. or is it just if I use the PB "String" functions like replacestring()and mid().
Could I use string pointers instead of mutexing?.. I just want to know if anyone has the beginnings of a list of which functions cause issues with strings in PB specifically.
Could I use string pointers instead of mutexing?.. I just want to know if anyone has the beginnings of a list of which functions cause issues with strings in PB specifically.
- Kaeru Gaman
- Addict

- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
I'm using PB 4.00 and I know about that option
but if there's something that's not threadsafe.. it just gives a genetic error.. not a specific line number.. I don't know how to write threadsafe code.. hence the question..
- Kaeru Gaman
- Addict

- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
an IMA could be caused by any stack-manipulation...
and it will always return no correct line-number in the error-message...
i'm sorry, i haven't dealt with string-shoving between threads so far....
i've read topics about list-gadget-filling in a thread, but i have no experience with it...
(never used a list-gadget... i'm a game-progger, i'm a algorithm-theoretical... but i'm not a windows-surface-freak...)
i only know basic thread-handling...
what exactly is the problem?
and it will always return no correct line-number in the error-message...
i'm sorry, i haven't dealt with string-shoving between threads so far....
i've read topics about list-gadget-filling in a thread, but i have no experience with it...
(never used a list-gadget... i'm a game-progger, i'm a algorithm-theoretical... but i'm not a windows-surface-freak...)
i only know basic thread-handling...
what exactly is the problem?
oh... and have a nice day.
