Yep, that looks good.

Strictly, it is not necessary to do the 'if (...)' statement at all. You 
can just always do the mHandler.post(...) instead.

On Tuesday, October 30, 2012 2:39:24 PM UTC-4, Jay Howard wrote:
>
> 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]<javascript:>
> > 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]<javascript:>
>> > 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]<javascript:>
>>> To unsubscribe from this group, send email to
>>>
>>> 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