Real Software Forums

The forum for Real Studio and other Real Software products.
[ REAL Software Website | Board Index ]
It is currently Tue May 22, 2018 10:28 pm
xojo

All times are UTC - 5 hours




Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Threads and Progress Bars - Ready to do it Right
PostPosted: Tue Mar 05, 2013 2:20 pm 
Offline
User avatar

Joined: Wed Feb 01, 2012 3:06 pm
Posts: 68
Okay, I think I'm ready to do a thread and a progress bar the correct way.

I have a fairly long and complex processing loop that can take a very long time when opening a large file. I have isolated the very core central processing of the loop and placed it in a stand-alone method in preparation to put that method into a thread. A couple quick questions before I make the final plunge...

First question: The main looping process (the thread) will be filling a database with information from the file being read . The next step after reading the file and loading the database (when the thread ends) is to fill a list box from the data in the database. Since I can't fill the list box until the thread ends, how do I get my process to suspend until the thread completes filling the database? That is, how do I essentially twiddle my thumbs until the thread ends?

Second question: Since the thread is reading a file and loading a database, there are some necessary error-checking processes that that could (in an extreme case) display a MsgBox with an error message informing the user of some unexpected error situation. Can I display a MsgBox in the middle of executing a thread?

Thanks to all - this is a really great support group.

Ron Bower
Ellicott City, MD

_________________
Ron Bower
Ellicott City, MD


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Tue Mar 05, 2013 3:12 pm 
Offline
User avatar

Joined: Mon Feb 05, 2007 5:21 pm
Posts: 600
Location: New York, NY
Use a Timer to monitor the progress of your Thread. The Thread can store information in its own properties that the Timer can check, and the Timer can see of the Thread is running and act when it's not.

No, you should not interact with the UI in any way from within a Thread. The way to handle this is to store an error code and/or message in a property of the Thread that your Timer checks once the Thread has finished. The Timer can display the message.

If it will take a while to fill the ListBox, you can either use something like my Data-On-Demand ListBox, or use another Timer that loops for loops for no more more than x ticks (I recommend 3), then stops until the next pass of the Timer. Your UI will stay responsive, and you can monitor and kill that Timer whenever needed too.

Some example code. First, the method that starts your Timer. (All properties are in a window or a module.)
Sub StartImport()
If ProcessThread <> nil and ProcessThread.State <> Thread.NotRunning then
ProcessThread.Kill
while ProcessThread.State <> Thread.NotRunning
App.YieldToNextThread
wend
end if

ProcessThread = new MyProcessThread
ProcessThread.Run
MonitorTimer.Mode = 2
End Sub

The MonitorTimer code:
if ProcessThread.State <> Thread.NotRunning then
return
end if

// Thread is over, so do your thing
me.Mode = 0 // Stop this timer

Code for the timer that fills the ListBox
dim entryTicks as integer = Ticks()
for row as integer = LBStartingRow to LastIndexOfMyData
// Fill a row
LBStartingRow = row + 1
if ( Ticks() - entryTicks ) > 3 then
me.Mode = 1 // Do more later
return
end if
next i
// Wrap up
me.Mode = 0

_________________
Kem Tekinay
MacTechnologies Consulting
http://www.mactechnologies.com/

Need to develop, test, and refine regular expressions? Try RegExRX.


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Tue Mar 05, 2013 3:38 pm 
Offline
User avatar

Joined: Wed Feb 01, 2012 3:06 pm
Posts: 68
Kem -

I think I'm about 80% there - just not seeing something...

Let me see if I can explain my "deer in the headlights" moment.

So, I have a process that will launch the thread and I have a timer that will keep interrupting me so I check check to see if the thread has completed.

How do I throw the code into a "do nothing" loop while it's waiting for the timer to interrupt to check if the thread has finished ?

I'm somehow envisioning something like...

Start the thread
Setup a Timer to interrupt me and update the progress bar
While ( thread is running )
twiddle thumbs
Wend


What is the "twiddle thumbs" code - or, maybe I'm not as ready as I think I am.

Ron Bower
Ellicott City, MD

_________________
Ron Bower
Ellicott City, MD


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Tue Mar 05, 2013 4:11 pm 
Offline
User avatar

Joined: Mon Apr 02, 2007 2:08 am
Posts: 1225
Location: San Francisco, CA, USA
Edit: I may have misunderstood your question...

Twiddling thumbs in a thread is easy:

While ( thread is running )
App.YieldToNextThread()
Wend


Yielding to the next thread also allows the timer's Action event to run (since it's on the main thread) if its period has expired.

_________________
Boredom Software


Last edited by charonn0 on Tue Mar 05, 2013 4:16 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Tue Mar 05, 2013 4:13 pm 
Offline
User avatar

Joined: Mon Feb 05, 2007 5:21 pm
Posts: 600
Location: New York, NY
There is no "twiddle thumbs" code". You start the Timer, then exit. The Timer is handling the twiddling of thumbs until the thread is finished.

_________________
Kem Tekinay
MacTechnologies Consulting
http://www.mactechnologies.com/

Need to develop, test, and refine regular expressions? Try RegExRX.


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Tue Mar 05, 2013 4:23 pm 
Offline

Joined: Fri Jan 06, 2006 3:21 pm
Posts: 12388
Location: Portland, OR USA
Quote:
How do I throw the code into a "do nothing" loop

This should never be necessary.


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Tue Mar 05, 2013 4:50 pm 
Offline
User avatar

Joined: Mon Feb 05, 2007 5:21 pm
Posts: 600
Location: New York, NY
To expand on Tim's point, Real Studio is an event-driven, object-oriented, not procedural, language. Creating a "twiddle thumbs" loop is a procedural way of doing this, whereas using the main event loop (which Real Studio manages for you) is the OOP way (and the "right" way) to do it to provide the best experience for your users.

Think of it as one guy who has to do every task before him, vs. a manger that can delegate to others, then walk away until needed again.

_________________
Kem Tekinay
MacTechnologies Consulting
http://www.mactechnologies.com/

Need to develop, test, and refine regular expressions? Try RegExRX.


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Wed Mar 06, 2013 7:41 am 
Offline
User avatar

Joined: Wed Feb 01, 2012 3:06 pm
Posts: 68
Okay, thanks for all the help (and patience)...

I'll try doing some code testing within the next few days.

Ron Bower

_________________
Ron Bower
Ellicott City, MD


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Wed Mar 06, 2013 10:30 am 
Offline

Joined: Tue Aug 14, 2007 8:44 am
Posts: 583
Note: if you try to include the progress bar in a container control and place that in a tab panel or page panel, the progress bar is likely to disappear.


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Thu Mar 07, 2013 8:38 am 
Offline
User avatar

Joined: Wed Feb 01, 2012 3:06 pm
Posts: 68
I'm making progress in "baby steps" - intentionally as I really want to master this process (no pun intended).

So, I have the main file loading code within the Run Event of a Thread Object that I added to the Project. I Named the Object "Thread Processor".

I also have added a Progress Bar, Progress Integer Property, and a Timer to the Main Window. The Progress Bar is normally invisible and the Timer is normally off.

The Code in the timer is simple enough:

Progress = Progress + 5 // Progress is the Integer Property added to the Main Window
If ( Progress > ProgressBar1.Maximum ) Then
Progress = 0
End If
ProgressBar1.Value = Progress


Then when I'm ready to run the Thread, the following code is executed:

Main.ProgressBar1.Visible = TRUE
Main.Progress = 0
Main.Timer1.Period = 250
Main.Timer1.Mode = Timer.ModeMultiple
Main.Timer1.Enabled = TRUE

Dim ProcessThread As New ThreadProcessor
ProcessThread.Run

While ( ProcessThread.State = Thread.Running )
App.YieldToNextThread
Wend

Main.Timer1.Mode = Timer.ModeOff
Main.ProgressBar1.Visible = FALSE


So... The Thread executes beautifully, the GUI stays responsive, but the progress bar does nothing. In fact, from what I can tell, the Timer1 Events don't even occur.

Somehow it seems that the "App.YieldToNextThread" completely suspends the current thread - even eliminating the timer events.

What am I doing wrong and how can I get the progress bar to update from the Timer Event ?

Ron Bower
Ellicott City, MD

_________________
Ron Bower
Ellicott City, MD


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Thu Mar 07, 2013 9:49 am 
Offline
User avatar

Joined: Mon Feb 05, 2007 5:21 pm
Posts: 600
Location: New York, NY
I think there is a fundamental misunderstanding about what Timers are and what they do.

A Timer should more appropriately be called an "Idler" in that its code runs in the main thread once or periodically, depending on the setting of mode, starting after the Period interval from when the Timer's mode is set or Timer.Reset is called. If mode is 2, it will run again sometime after Period time has elapsed and the app isn't running any of your other code, and will continue to run periodically until the Mode is changed.

If you set a Timer, it's code will run without any further interaction from you, but it must have idle time to do it. You're not giving it idle time because your main code is looping endlessly and calling App.YieldToNextThread needlessly.

Get rid of that loop and rely on the Timer to do what the Timer does.

Your main code should end with
ProcessThread.Run

The Timer code should be:
if ProcessThread <> nil and ProcessThread.State <> Thread.NotRunning then
Progress = Progress + 5 // Progress is the Integer Property added to the Main Window
If ( Progress > ProgressBar1.Maximum ) Then
Progress = 0
End If
ProgressBar1.Value = Progress
else
Main.Timer1.Mode = Timer.ModeOff
Main.ProgressBar1.Visible = FALSE
me.Mode = 0 // Turn off this Timer
end if

Finally, why isn't the Thread filling in the Progress property with its actual progress instead of you guessing at it?

_________________
Kem Tekinay
MacTechnologies Consulting
http://www.mactechnologies.com/

Need to develop, test, and refine regular expressions? Try RegExRX.


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Thu Mar 07, 2013 11:59 am 
Offline
User avatar

Joined: Wed Feb 01, 2012 3:06 pm
Posts: 68
Kem -

Thank you so much for spending as much time on this as you have. I truly believe that a whole lot of my application should be re-written from scratch with the understanding of threads that I now have - thanks to you and others on this forum.

To directly address your points... In my original post I stated:
First question: The main looping process (the thread) will be filling a database with information from the file being read . The next step after reading the file and loading the database (when the thread ends) is to fill a list box from the data in the database. Since I can't fill the list box until the thread ends, how do I get my process to suspend until the thread completes filling the database? That is, how do I essentially twiddle my thumbs until the thread ends?

So, if I end my main code with launching the thread, then the next thing my (as-is) application will try to do is to fill the list box from the database that the thread is creating - but the data won't be there yet unless I wait for the thread to complete. It almost seems like I need some form of state-machine that will recognize when the thread ends and then launch the process to fill the list box from the database.

Regarding the thread filling in the progress property itself, it's just a matter of doing this in very simple steps. Get the basic core working, then improve a bit at a time.

Thanks for all your help and patience.

Ron Bower
Ellicott City, MD

_________________
Ron Bower
Ellicott City, MD


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Thu Mar 07, 2013 12:06 pm 
Offline
User avatar

Joined: Mon Feb 05, 2007 5:21 pm
Posts: 600
Location: New York, NY
Right, that "process" that will monitor the thread and fill the ListBox when it's finished can be the same Timer that updates the progress bar.
if ProcessThread <> nil and ProcessThread.State <> Thread.NotRunning then
// The thread is still running
Progress = Progress + 5 // Progress is the Integer Property added to the Main Window
If ( Progress > ProgressBar1.Maximum ) Then
Progress = 0
End If
ProgressBar1.Value = Progress
else
// The thread is finished, so fill the ListBox
MethodThatFillsListBox()

Main.ProgressBar1.Visible = FALSE
me.Mode = 0 // Turn off this Timer
end if

_________________
Kem Tekinay
MacTechnologies Consulting
http://www.mactechnologies.com/

Need to develop, test, and refine regular expressions? Try RegExRX.


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Thu Mar 07, 2013 2:06 pm 
Offline
User avatar

Joined: Wed Feb 01, 2012 3:06 pm
Posts: 68
Kem -

Okay, I'm there now - Some basic cleanup and careful checking as this is a general-purpose routine that is called from a few other places. But, at first check, they all seem to be working fine.

One more "mentoring moment" please...

I note that you use "ProcessThread.State <> Thread.NotRunning" rather than "ProcessThread.State = Thread.Running"

I ASSUME that is because the State could be "Sleeping", "Waiting", or "Suspended" - is that the reason ?

Ron Bower

_________________
Ron Bower
Ellicott City, MD


Top
 Profile  
Reply with quote  
 Post subject: Re: Threads and Progress Bars - Ready to do it Right
PostPosted: Thu Mar 07, 2013 2:07 pm 
Offline
User avatar

Joined: Mon Feb 05, 2007 5:21 pm
Posts: 600
Location: New York, NY
Exactly right. I learned that the hard way. :-)

_________________
Kem Tekinay
MacTechnologies Consulting
http://www.mactechnologies.com/

Need to develop, test, and refine regular expressions? Try RegExRX.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group