Here's what I ended up doing:

1. Ensure that my timer class, which creates a Handler in its <init> method
on the caller's thread, is always instantiated on the main thread.
2. My class is also a BroadcastReceiver, but onReceive() is guaranteed to
be called by the main thread so it can access the handler directly.
2. Structure each external method that accesses the handler (and that could
potentially be called from multiple threads) as follows:

private void doSomethingWithHandlerSync() {
  // access the handler directly
}

public void doSomethingWithHandler() {
  if (Thread.currentThread().equals(mHandler.getLooper().getThread())) {
    doSomethingWithHandlerSync();
  } else {
    mHandler.post(new Runnable() {
      @Override
      public void run() {
        doSomethingWithHandlerSync();
      }
    });
  }
}

Does that thread check look right?  Seems like it should be sufficient to
guarantee that doSomethingWithHandlerSync(), handleMessage() and
onReceive() will never execute concurrently.


On Tue, Oct 30, 2012 at 10:09 AM, Jay Howard <[email protected]>wrote:

> Thanks so much for the response!  If you'll indulge me with a few more
> questions...
>
> So I instantiate the handler in the onCreate() method of my Application,
> which I assume means it's tied to the UI thread.
>
> The method that removes and re-sends messages is called primarily on the
> UI thread, but can also be called from an IntentService that I use to
> handle network communication.  Since the service is executed by a thread
> other than the UI thread it appears that I do need to synchronize.
>
> To give some more detail on my goals for this:  I'm attempting to use the
> handler to track both user inactivity and server session expiration.  The
> Service calls a "session refreshed" method to remove session-related
> delayed messages and re-add them with a new delay.  The UI thread calls an
> "user activity occurred" method to indicate the user "did something"; that
> method removes inactivity-related delayed messages and re-adds them with a
> new delay.
>
> One other kink:  I also have code to respond to SCREEN_ON and SCREEN_OFF.
> At screen off I remove all messages from the handler; at screen on I
> re-send each message that was queued at the point at which screen off
> occurred, albeit with a revised delay to account for the time that elapsed
> while the screen was off.
>
>
>
> On Tue, Oct 30, 2012 at 9:43 AM, Streets Of Boston <
> [email protected]> wrote:
>
>> It depends which thread is callling the code-snippet you show above (the
>> one calling 'removeMessage').
>>
>> If your code, calling 'removeMessage', is run on the same thread that is
>> tied to the *handler*, you're fine. The message you sent will not be
>> handled/run until your code finishes first. No extra work necessary.
>>
>> If your code, calling 'removeMessage' is run on another thread than the
>> one tied to the *handler*, you need to sync it up. This could be as
>> simple as send another message on that handler that will call
>> 'removeMessage': E.g.:
>> handler.post(new Runnable() {
>>   public void run() {
>>     // Right now, calling 'removeMessages', etc. is done
>>     // on the handler's thread as well.
>>     handler.removeMessages(MSG_**ONE);
>>     handler.removeMessages(MSG_**TWO);
>>     ...
>>
>>     if (conditionOne)
>>       handler.**sendEmptyMessageDelayed(MSG_**ONE, timeoutOne);
>>
>>     if (conditionTwo)
>>       handler.**sendEmptyMessageDelayed(MSG_**TWO, timeoutTwo);
>>   }
>> });
>>
>> Since both the 'removeMessages' and 'sendEmptyMessageDelayed' are called
>> on 'handler' the Runnable needs to finish first before any other message
>> sent to 'handler' can be executed.
>>
>>
>> On Tuesday, October 30, 2012 9:17:39 AM UTC-4, Jay Howard wrote:
>>>
>>> I'm using a timer to manage timeout events, and would like to ensure
>>> that a particular method runs atomically without the handler issuing
>>> messages while the method is executing.  Its basic form is:
>>>
>>> handler.removeMessages(MSG_**ONE);
>>> handler.removeMessages(MSG_**TWO);
>>> ...
>>>
>>> if (conditionOne)
>>>   handler.**sendEmptyMessageDelayed(MSG_**ONE, timeoutOne);
>>>
>>> if (conditionTwo)
>>>   handler.**sendEmptyMessageDelayed(MSG_**TWO, timeoutTwo);
>>>
>>> ...
>>>
>>> What I want to avoid is a situation where, before the removeMessages()
>>> calls execute, one of the messages reaches its timeout and is delivered to
>>> the message queue, then I send a duplicate one immediately after.  My goal
>>> is to guarantee that there is never more than one of each message type "in
>>> flight" on the handler at any given time.
>>>
>>> Does the Handler class synchronize on MessageQueue when delivering its
>>> messages?  If so, then could I just synchronize on the MessageQueue?  Or
>>> would that be a terrible idea, since it's used by entities other than just
>>> my Handler?
>>>
>>  --
>> 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
>>
>
>

-- 
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