FWIW -- I just did go look at the source for Timer, and cancel() does exactly what I expected.
It synchronizes on its internal queue, sets a flag, clears the queue, and does queue.notify(). On Apr 19, 12:20 am, Bob Kerns <[email protected]> wrote: > What he's doing there is specific to using a timer. I'm sure > internally, it tells the timer thread to stop processing tasks and > exit, just like I outlined earlier. > > Generally speaking -- if you have a facility that provides a way to > wake it up, when trying to end a task, it's good to wake it up so it > can die. For example, setting a flag and calling notifyAll() to > unblock a thread waiting in wait(). I expect this is what calling > Timer.cancel() does, though I haven't looked at the source. > > If a Timer meets your needs, then I recommend using it; it will be > much simpler than any approach you came up yourself. However, remember > that a single timer only uses a single thread, so if it does something > that takes a long time, other scheduled tasks won't run until it > finishes. This can be a reason to use separate timers for different > tasks. > > Note that this won't solve your problem above -- because calling > Timer.cancel() won't do anything to terminate YOUR loop. It terminates > the scheduling loop that waits on and runs tasks. It doesn't stop the > tasks once they're running. > > On Apr 18, 8:21 pm, Tejas <[email protected]> wrote: > > > > > Hi Bob, > > > Thanks a lot for this. This helped me to understand a lot of things. > > I found out a good way for starting/stopping a service > > here:http://www.brighthub.com/mobile/google-android/articles/34861.aspx > > > What do you think of this one ? > > Cheers, > > Tejas > > > On Apr 18, 7:03 pm, Bob Kerns <[email protected]> wrote: > > > > OK, I understand your thinking a bit better, so hopefully I can > > > explain a bit better. > > > > onDestroy() is only called when your application is idle. The system > > > will NEVER directly call a lifecycle method except when the main > > > thread is idle If you are running some long-lived function from, say, > > > onStart(), or a handler in the main thread. All of these are handled > > > one at a time by the main thread's Looper. > > > > So there will be no abrupt termination of your function when > > > onDestroy() is called. That only happens if it kills off the process. > > > Which is a lot more likely to happen if you block the main thread -- > > > after a while, the user will get a dialog offering to kill or wait for > > > the busy process! > > > > Java used to support interrupting and abruptly terminating threads. > > > However, there is absolutely NO way to make this a safe operation. > > > Android does kill off processes, which can leave things outside the > > > process in an inconsistent state, but that's not as bad as having your > > > application still running, but in an inconsistent state internally! So > > > abruptly force-quitting a method is not part of the model of any Java > > > system. (But you can still check, and throw an exception to get out of > > > a loop -- that will properly invoke all finally() clauses on the way > > > out, etc.). > > > > It's hard for me to tell you the "proper" way to stop your service, > > > because it depends on just what you're doing. You have part of the > > > idea, by checking for a termination flag in your loop. You can set > > > that in your onDestroy() method -- akin to what you're trying to do > > > with your call to the undocumented Looper.quit() method. But what you > > > want to do is to set your CARuntimes.MainServiceRunFlag instead. > > > (Except I'd make that an instance member of your Service class, rather > > > than a static of some other class. Better modularity, though you can > > > make it work this way). > > > > It looks to me like what you're really trying to do, is what the > > > system already provides for you better -- IntentService. I really > > > don't know what their intent was, calling it this -- I think I'd call > > > it ThreadedService, since the relevant point is that it runs your code > > > in a separate thread. Or maybe HandlerThreadService, since it uses a > > > handler to serialize the requests for work. You still have to be > > > careful about things that queue up things to the current thread's > > > looper -- like Toast, for example. Any deferred processing you want to > > > queue up to a handler you set up in the IntentService's onCreate > > > method (i.e. on the main thread). > > > > Anyway, the purpose of HandlerThread's and Handler's is not clean > > > shutdown, but rather the queuing of messages via a Looper and > > > associated MessageQueue. If you're only handling one message, ever, > > > then creating your own thread would make sense. An AsyncTask would be > > > a good choice if you're only running for a short time (but too long > > > for the main thread). But if this is something that runs for an > > > extended period of time, it would potentially block other uses of > > > AsyncTask, so your own thread is a better choice. > > > > So anyway, to summarize -- Handler's, HandlerThread's, and > > > IntentService give you a way to do one thing at a time in another > > > thread. AsyncTasks give you a way to do a small number of small things > > > in parallel (in some versions of the system, one thing at a time). > > > Long-lived things need their own threads -- HandlerThread and > > > IntentService can provide this. You stop a thread by testing for some > > > condition in the loop in the thread. If the thread needs to wait, use > > > wait(), and use notifyAll() to wake it up after you set the flag. Be > > > sure to use the synchronized keyword to coordinate in this case! And > > > if you loop within a handler, you're basically occupying that thread > > > while you're looping. So be careful not to queue up any additional > > > work to that thread's looper. (And often it needs to go to the main > > > thread anyway -- for example, all GUI operations need to be run > > > there). > > > > Sorry I can't make all that simple! Threading is never really simple. > > > But there are simple patterns, and if you carefully stay within those > > > simple patterns, you can avoid most of the complexity. > > > > Finally, about getApplicationContext() -- unfortunately, in the > > > released versions of the documentation, there are some bad examples > > > around this. I understand they've been fixed for the next release of > > > the SDK. But if you're in an Activity or a Service, you just supply > > > that activity or service, via the "this" pseudo-variable. However, in > > > your case, your use isn't directly in the service, but in your nested > > > ServiceHandler class, so "this" will refer to that instance instead. > > > But you can still refer to the outer instance's this, by writing > > > "ManagerService.this". You could also arrange to pass the context in > > > ass a parameter when you create your ManagerService -- but since the > > > system already does that work for you with a nested class, there's no > > > reason. Just replace getApplicationContext() with ManagerService.this, > > > and you're set. > > > > . > > > On Apr 18, 11:08 am, Tejas <[email protected]> wrote: > > > > > > If you're going to do that, why involve a handler > > > > > at all? > > > > > Now suppose, I use any other function in my service class instead of > > > > handler and say I'm performing a time consuming task in that function. > > > > If the onDestroy method of the service is called, I assume that it > > > > will terminate my function abruptly. I'm not sure of this, but I > > > > thought so and hence used the Handler thread to have a proper > > > > shutdown. please correct me if I'm wrong. Also let me know the right > > > > way to stop the service. > > > > > > Finally, never, ever, call getApplicationContext(). The return value > > > > > is not useful to us mortals. Supply the service itself as the context. > > > > > I'm still not sure what are you saying. How will you supply the > > > > service as the context ? Can you provide an example ? > > > > > On Apr 18, 2:56 am, Bob Kerns <[email protected]> wrote: > > > > > > Actually, just because something is a background service does NOT mean > > > > > it is running in a different thread. > > > > > > Background services run in the main thread. I suspect that this point > > > > > of confusion may be involved in your problem, though I don't quite > > > > > spot the problem. > > > > > > Also, you have a handler there that basically loops forever. That's > > > > > kind of an oxymoron. If you're going to do that, why involve a handler > > > > > at all? If I parse it correctly, it's not the main thread it'll be > > > > > blocking, but still... if something in that thread is posting via that > > > > > thread's looper rather than the context, that won't be processed. > > > > > > Finally, never, ever, call getApplicationContext(). The return value > > > > > is not useful to us mortals. Supply the service itself as the context. > > > > > To make things maximally confusing, getApplicationContext() will > > > > > appear to work in most circumstances. But it's always the wrong way to > > > > > get a context to use. > > > > > > On Apr 17, 2:05 pm, Tejas <[email protected]> wrote: > > > > > > > Ah... I got this working. Still I'm not sure of the reason for this > > > > > > (some thread issue I suppose) It would be great if someone can throw > > > > > > some light on this. > > > > > > > I was instantiating the sensor class in a background service.So the > > > > > > thread in which it was running was different than the main thread. > > > > > > I was doing something like this: > > > > > > > public class ManagerService extends Service { > > > > > > > private final String LTAG = this.getClass().getName(); > > > > > > private volatile Looper mServiceLooper; > > > > > > private volatile ServiceHandler mServiceHandler; > > > > > > > private final class ServiceHandler extends Handler{ > > > > > > public ServiceHandler(Looper myLooper) { > > > > > > super(myLooper); > > > > > > } > > > > > > > public void handleMessage(Message msg) { > > > > > > Log.v(LTAG, "handleMessage > > ... > > read more » -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en

