Threaded NSTimer: how to cancel?
Hi everybody,
in one of my applications I have a threaded NSTimer. The relevant code is
NSThread *rendThread;
NSTimer *threadTimer;
float delay=0.02;
- (void) doRend {
// do stuff...
}
-(void) threadTimer{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRunLoop *runloop=[NSRunLoop currentRunLoop];
timerRend=[NSTime scheduledTimerWithTimeInterval:delay target:sel selector:@selector(doRend) userInfo:nil repeats:YES];
[runloop run];
[pool release];
}
-(void) startRendThr{
rendThread = [[NSThread alloc initWithTarget:sel selector:@selector(threadTimer) object:nil];
[rendThread start]; //start the thread
[rendThread release];
}
by calling [self startRenderThr] the timer is nicely spawned in a new thread. Later on, I would like to stop the timer and *kill* this thread, in order to start a new instance with a different time delay.
Of course, I can invalidate the timer
[timerRend invalidate];
timerRend=nil;
but I can't find a way to kill the bloody thread. Any idea about how to wave rendThread goodbye?
Thanks in advance!
Fabio
Hi Fabio
I'm surprised that there's no method NSThread -terminate (or something like that). Maybe if you release the thread (so that it's dealloc method is called), it'll die.
Another thought however is, "are you rendering all the time?" - do you need to kill the thread. What I'm thinking about is my tutorial Clock. I use timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(update) userInfo:nil repeats:YES]; and then I don't need a thread at all. My timer wakes me up every second. Of course I have almost nothing to do when I wake up (simply update clock for the user) so this works well. If you're rendering for seconds at a time, this approach isn't good because the application UI will be frozen while you're rendering.
Remember that killing a thread is an explosive event. There's an MPExit thing. However you can leak resources like crazy (depending on what you're doing).
NSThread has a cancel and isCancelled. So you could consider using that. Within your rendering code, you should be able to test isCancelled and exit gracefully in a controlled manner when the user/UI requires you to stop rendering. Less explosive, more controlled and reasonable.
Dear Robin,
thanks for the pointers. I investigated the isCancelled method but, at the end of the day, I found a nice solution. Keep the threads open. When I invalidate the timer and set it again, it stays in the thread. Nice and easy!
Yes, I want threaded NSTimer. I have two of these: one is the rendering, capped at the user-wished FPS, and one is the calculation which is async and goes much faster (like every millisec or so). And then there's the UI which is independent of both. What I like is to use concurrently the resources. This way, my simulation is smooth *and* fast...you should see the little thing I'm very proud of :)
Thanks again!
Ciao
Fabio
Fabio
I would like to see this gem you have made. How? We could use TeamViewer. I'm sure kompilesoft is also interested to see what you've done. Maybe sometime at the weekend (Sunday evening for you, Sunday morning for me, and Sunday lunch-time for K) ? (or Saturday if you prefer)
Or you could zip it and post it here (for anybody to see). Or zip and e-mail it to me at home. I'll build it and run it. However I'm sure it will really come alive when you explain what's cookin' - and that's where TeamViewer comes to play.
Hi Robin,
don't get me wrong, the beauty is in the final result - alas not in the code which is a mess (and even more a mess at this stage) In the end, I am a physicist and even though this is not an excuse to write bad code, I never learned to write in an elegant way (code, at least)... :) The reason why I am so happy is that the program runs faster than the Carbon stuff and is a lot more intuitive to use (in Carbon, all controls were keyboard-controlled, now everything is in the UI except a few accelerators like the space bar to pause-resume the simulation) - it almost has a Mac-feeling. That's what I was looking for!
Nevertheless, sure I can send you the (ugly) code...I need a couple of days to finish implementing a few things (including the damned print routine) and polish it up a bit...Are you particularly against the use of global variables :) ? For the moment, you can be an alpha-tester if you wish :) Attached here is a build of the whole thing. If you wish so and have time, feel free to play with this. You should see some "balls" which arrange themselves in several different configurations. The view is controlled by dragging the mouse and you can zoom-in/out by scrolling up or down (two-fingers gesture) or ctrl+left dragging up/down. You can choose the number of particles between 2 and 1000 and create 2D or 3D structures via the UI. The help is *not* updated (is for the Carbon stuff).
*** Physics spoiler *** The program simulates a number of particles (electrons tipically) which are confined in a circular/spherical trap and repel due to electrostatic forces. The competition between repulsion and confinement creates the structures you see, called Wigner molecules after the name of Wigner, a famous physicist. They are funny. In 2D, one would naively expect all particles to arrange in a polygonal fashion. This is true only up to 5, however. Six particles arrange as a pentagon with a particle in the middle (this is called "shell structure", much like in atom physics). You can also have a hexagon, but with a higher energy (and thus unstable). Try to reproduce these in the program :) Increasing the number of particles, several different configurations compete and it is tough to tell which is the "good" packing (not to mention in 3D!). Hence the program. *** End physics spoiler ***
Still, it amuses me how it is easy (writing "spaghetti code"!) to be "operative" in Cocoa even without a formal training in that...and the environment stimulates me to implement features which usually I would not bother to develop (save/open the status....). In my other project (the magnet simulation if you remember) I ended up adding a text-box for on-the-fly note taking. This, together with the ability to save the status of the simulation makes the program very effective to create many different "scenarios" which can be used in teaching demonstrations without spending time tweaking sliders and buttons...Without cocoa, I would *never* have thought to do such a thing.
Attachment: CocoWm.zip (462.0KB)
Goodness, I can feel your excitement. This think looks AMAZING. Of course, I've no idea what it's actually doing. Looks like a game of snooker or something (I know it's not). I can't get the keyboard to work. The keyboard "beeps" when I hit any key - or does it need ctrl or cmd or something?
I try to avoid static variables. In simple programs, they work well. On larger programs (especially if you have multiple documents), statics are a source of trouble because they are seldom thread safe. For example, if you can open multiple windows and render different scenarios simultaneously, you'll probably discover you're blocked by statics - and adding critical sections (and other locking gizzmos) usually makes it worse (the program can deadlock). Yuck!
However, I know you're on a great big roll here. Get the program working, amaze the folks around you. Reworking can come later if it gets a lot of use. If it dies the death of "oh well, it's bla bla bla", then there's no reason to optimize and polish it. Right?
Sure, please send me the code. I'll read it and give you feedback privately by email.
Robin,
thanks! I'll clean it up and send to you. Some statics are for laziness (didn't feel like defining structs for the parameters and pass them around). Some are indeed very useful for parallel processing: the calculation thread spits out the particle positions and the rendering thread places them on the view. Since only one thread writes and one reads, it is very handy to have the threads communicate via a shared memory segment (rather than passing data around - the MPI way if you want). And, I don't particularly need to be picky if, when the rendering occurs, the calculation has not yet finished to cycle over the particles: the frames are dense enough not to cause a problem in the visualization :)
And...you're right. There's no point in spending *too much time* if the program is not of interest...after all, I have my toy :)
Ciao
Fabio
Please cc' me for the code.
'twill be done, when the code is sufficiently stable and "clean" :)