Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > threading virgin. could use some advice

threading virgin. could use some advice
Thread Tools
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Apr 5, 2003, 09:36 AM
 
I just created my first thread and have a few questions about interaction between the thread and the main process.

I'm writing a simple application that gets some data from the web, parses it, and then populates some fields in the main window. I have a timer set to get the info every five minutes. Here's some pseudo code:

Code:
awakeAtNib call threadStartMethod threadStartMethod [NSThread detachNewThreadSelector: getInfoMethod] getInfoMethod generate autorelease pool [progressBar startAnimation:self] <get info off web site> populate fields in main window [pregressBar stopAnimation:self] release pool reset timer
Here are my questions:
1) Is it okay to populate fields in the main window within the thread? It seems to work, but my cursory reading seems to indicate that interaction between threads can be tricky. Am I just getting lucky that it works?

2) Is it okay to set the timer within the thread?

thanks,
kman
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Apr 5, 2003, 10:06 AM
 
I now realize that starting the NSTimer within the thread won't work as it will obviously be destroyed when the thread ends. How do I go about creating a timer? I think it requires me to send a notification to the main thread when the getinfo thread end, but I'm not sure how to do that.

thanks,
kman
     
Mac Elite
Join Date: Sep 2001
Location: The Land of Beer and Chocolates
Status: Offline
Reply With Quote
Apr 5, 2003, 12:21 PM
 
Why don't you just create the timer in the main thread and make it fire threadStartMethod every five minutes? I don't see why you'd need to have the timer in the other thread.
     
Mac Elite
Join Date: Sep 2001
Location: The Land of Beer and Chocolates
Status: Offline
Reply With Quote
Apr 5, 2003, 12:27 PM
 
Code:
myTimer = [[NSTimer scheduledTimerWithTimeInterval:refreshInterval target:self selector:@selector(threadStartMethod) userInfo:nil repeats:YES] retain];
Just do that in awakeFromNib, and don't mess around with the timer in any other thread. The timer in the main thread will just make sure the method is fired every five minutes. When you want to stop it you just do [myTimer invalidate]; etc. Hope that helps
     
Senior User
Join Date: Dec 2001
Status: Offline
Reply With Quote
Apr 5, 2003, 01:17 PM
 
Trying to simplify a bit to get you started out right:

1. Data is global. All threads share the same memory in your application, which makes accessing the same data from multiple threads hazardous to your (and your user's) health.

2. The "thread" of execution is local to the, um, thread. Any methods or notifications called in one thread will not leave that thread. (As a general rule, which should only be broken when absolutely neccessary, and even then, the breakage should be hidden as well as possible.)

So basically anything you execute from a thread will execute in that thread. Timers are no exception. When you create a timer, it doesn't do anything unless it is added to a run loop. If you create a timer with convenience methods in your application's main thread, they are automatically added to your application's run loop, and will be called at idle time. If you do the same thing in another thread, they are added to that thread's run loop. The catch here is that you must explicitly create a run loop (if you want one) for that thread and manually "run" it. If the run loop does not "run", the timers attached to it will not fire.

As for notifications, they are always posted on the same thread that sent them, so that will not achieve your goal.

If you want to create timers in a separate thread that attach themselves to the main thread's run loop, you need a connection between the two threads, provided by the aptly named NSConnection class. You should establish this connection as the first order of business when you start your thread. Apple's thread documentation describes how to do this quite well. Aside from delving into the pthread interfaces, this is the only way to "safely" communicate between threads.

As for interacting with the UI from a thread, according to Apple, this has been made much safer in Jaguar. In 10.1, if you called -[NSView display] from a thread, ApplicationKit would actually dispatch this method to the main thread. In 10.2, Apple states that this method will now run in the calling thread (although -[NSView setNeedsDisplay: YES] will cause -[NSView display] to run in the next iteration of the main thread's run loop). So, in theory, it is safe. In practice, I set up an NSConnection to manipulate the GUI from a thread.

To reiterate Jan Van Boghout's concerns, I have trouble understanding why you need to create a timer from a thread. Most of the time when you think this needs to be done, you will eventually realize that almost any situation can be handled with more elegance by simply creating a timer from the main thread whose method checks for a certain condition before doing anything.

Finally, if you find you really need a "timer thread", ie a thread that does something every x seconds regardless of whether the main thread is tied up, simply do [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: x]], where x is the number of seconds you want the thread to wait before continuing. But really, try to just use a timer from your main thread.
"Think Different. Like The Rest Of Us."

iBook G4/1.2GHz | 1.25GB | 60GB | Mac OS X 10.4.2
Athlon XP 2500+/1.83GHz | 1GB PC3200 | 120GB | Windows XP
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Apr 5, 2003, 01:17 PM
 
Thanks. I guess my initial concern was if there was a problem in the spawned thread (web site down or something). What would happen if the timer initiated the same method while the previous method was still running?

I guess I'll just put some timeout code in the spawned thread to make sure it quits before the timer fires again.

thanks,
kman
     
Senior User
Join Date: Dec 2001
Status: Offline
Reply With Quote
Apr 5, 2003, 05:50 PM
 
Originally posted by kman42:
What would happen if the timer initiated the same method while the previous method was still running?
I'm not sure what you are asking. Assuming you are talking about 1 specific timer in 1 specific thread, it isn't possible for that timer to fire again until the thread returns to its run loop, which won't happen until after the timer's method returns.

If you are trying to report an error condition back the main thread, use an NSConnection to communicate between the threads.
"Think Different. Like The Rest Of Us."

iBook G4/1.2GHz | 1.25GB | 60GB | Mac OS X 10.4.2
Athlon XP 2500+/1.83GHz | 1GB PC3200 | 120GB | Windows XP
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Apr 6, 2003, 10:40 AM
 
Originally posted by macmike42:
I'm not sure what you are asking. Assuming you are talking about 1 specific timer in 1 specific thread, it isn't possible for that timer to fire again until the thread returns to its run loop, which won't happen until after the timer's method returns.

If you are trying to report an error condition back the main thread, use an NSConnection to communicate between the threads.
My difficulty is with what would happen if I have a timer in the main thread that fires a method which launches a second thread. If the thread does not finish its execution before the timer in the main thread fires that same method again, does it just launch another thread? From your explanation it sounds as if the timer won't be able to fire again until the spawned thread is finished executing.

kman
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Apr 6, 2003, 10:43 AM
 
One final point as I am trying to understand all of this. I now have two threads which are launched by a timer (from the main thread). Each of these threads is interacting with DIFFERENT text fields in the main window. All they are doing is replacing the text in those fields with newly derived data. Since they are populating different NSTextFields do I have to worry about any conflicts between the threads? There are no variables shared by the threads. They operate independently gathering data from two different web sites and then populating the text fields with the data.

thanks,
kman
     
Senior User
Join Date: Dec 2001
Status: Offline
Reply With Quote
Apr 6, 2003, 12:05 PM
 
Ahh, OK, got it now.

When your timer in the main thread detaches a new thread, your main thread continues running, so the timer *will* be able to fire again while the other thread is still running. The solution is either:

1) Have the thread launch only once, and have it sleep for whatever interval you had the timer set to.

or

2) Create an NSLock. Before the timer launches the thread, have it -[NSLock tryLock]. If it returns YES, detach the thread. If it returns NO (as it will if the thread is still running when your timer fires again), don't detach the thread. When the thread exits, have it call -[NSLock unlock] on the same lock.

As for the text field issue, for all intents and purposes, what you describe is perfectly safe. However, I would still use an NSConnection so that the GUI is updated from the main thread, if not for any other reason than good programming practice, and it will save your *ss when your code gets more complex.
"Think Different. Like The Rest Of Us."

iBook G4/1.2GHz | 1.25GB | 60GB | Mac OS X 10.4.2
Athlon XP 2500+/1.83GHz | 1GB PC3200 | 120GB | Windows XP
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 03:21 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2