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

Reply via email to