From: Joseph M. Newcomer on
See below...
On Fri, 30 Apr 2010 15:15:00 +0200, Simon <bad(a)example.com> wrote:

>On 2010/04/30 02:48 PM, Tom Serface wrote:
>> Hi Simon,
>>
>> Did you get an answer that works for you? I want to make sure your
>> problem got solved.
>>
>
>Hi,
>
>Thanks for the reply, in the end I just added a flag that does something
>like.
>
>// -----------------------------
>OnTimer( ... )
>{
> if( busy )
> {
> timer_is_complete = true;
> }
> else
> {
> DoSomething();
> }
>}
>
>...
>
>DoingSomStuff()
>{
> // do the stuff
****
Note that if this is a long computation in the main GUI thread, that you have not returned
to the message pump, and consequently no timer messages could have been processed, and
therefoere if the timer_is_complete flag was not set when you entered, it cannot be set
when you leave.

And you should not compare a bool variable to a bool literal; this is poor style. What
value to you think a bool variable has? And why aren't you just saying

if(timer_is_complete)

because all you are doing is comparing a bool value to true to form, guess what, ANOTHER
bool value! This is silly. Do you write if( (a > b) == true)?
joe
*****

>
> if( true == timer_is_comlete )
> {
> DoSomething();
> }
>}
>
>// --------------------------------
>
>But I am not 100% happy with it. I would prefer to pause the timer. That
>way, when you resume the timer the normal chain of events will happen.
****
Well, Microsoft did not take your happiness into consideration. There is NO WAY to pause
a timer! But the code seems to suggest you are getting the logical equivalent of it, by
delaying any pending timer notifications until you are done with your computation. The
if-test and second call to DoSomething is a waste of code space if this is done in the
main GUI thread, because you have not given the timer any chance to actually notify you or
set that boolean, as written.
****
>
>I could write my own timer class using a thread but this would add a lot
>over testing overhead to the current app.
****
Without a thread to do the work, the above code is pretty meaningless.
joe
****
>I will almost certainly create a branch with a bunch of tests before
>going live with it.
>
>Thanks again
>
>Simon
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Hector Santos on
Simon wrote:

> On 2010/04/30 08:26 AM, Joseph M. Newcomer wrote:
>> You described something you thought you wanted, to solve an undefined
>> problem.
>
> No, I asked 2 fairly straight forward questions, read my OP again.
> is it possible to pause a timer and is there a way to know how many ms
> remain.
>
>> ...state what problem you were trying to solve, so we could not offer
>> suggestions about what
>> might actually do the job, because we didn't know what you were trying
>> to accomplish.
>
> No, _you_ could not offer suggestions.
> Others did, and they very good suggestions, thanks.
>
>>
>> Actually, my own take on this is that if you have to keep checking as
>> you describe, you
>> need to redesign the application so this is not even a problem that
>> needs to be solved.
>> You are tyring to retrofit something into an existing app that it was
>> not designed to
>> handle, and you are probably approaching the problem incorrectly.
>
> No, this is the wrong assumption.
>
> I could write a book about the application and _then_ ask my question(s).
>
> Or I could try to be as short and to the point as possible in order to
> get some help/insight/tips.
>
> Even the one example I gave had to be short and to the point.
> Any programmer would understand that.
>
> This is not an architecture design meeting room, this is a NG.
>
> Regards,
>
> Simon

Note speaking for Joe, what Joe was trying to express that you
(speaking in general) can get different answers when you provide a
small background or reason, this is especially true when you already
know the answer to the "pause" question about timers.

For example, in lieu of reasons, I provided an answer based on the
clues you provided:

::SetTimer( m_hWnd, TIMER_IDENT, 600000, NULL ); // WM_TIMER sent to
CWnd queue

where the hints here

- a Window handle m_hWnd, and
- a Timer ID
- A large frequency, 10 minutes

means you would have a CWnd::OnTimer() handler and you have the
ability to work with timer id passed to it to deal with the 10 minute
event. If you had another timer id with a different frequency, then
it normally means you need to check for the timer id event.

I find a lot of times people don't realize the timer id can be used in
the OnTimer(UINT nIDEvent) message even. Hence I provided one
implementation based the hints where you have a wait countdown with
the idea you can pause the countdown as you r original questions
"implied" - a pause in some "timer countdown." You didn't saw how
the pause happens, so I presumed it would be a button or something.

But after you followed up with the actual logic you are looking for:

OnTimer()
{
if( busy_doing_something_important )
{
// check again in 10 seconds
}
else
{
check_for_transactions()
}
}

that changes the picture and I would of provided a different answer as
it bring into question a "design" question of even needing this 10
minute timer, and also make the applet more dynamic, with no lost of
timed events.

In other words, its more dynamic for your check_for_transactions().

For example, you indicated you can be busy for more than one reason.
You didn't indicate the frequency of the check_for_transactions(), but
lets assume its done every 1 second because the recheck would be done
by seconds (every 10 secs).

So you could have a design where you have the following, and I will
show two versions of the following CBusyTask class to illustrate how
the requirements may alter depending on your implementations needs:

class CBusyTask {
public:
CBusyTask() : m_BusyCount(0) {}
void Clear() { m_BusyCount = 0; }
void Enter() { m_BusyCount++; }
void Exit() { if (m_BusyCount > 0) m_BusyCount--; }
BOOL IsBusy() { return m_BusyCount > 0; }
LONG Count() { return m_BusyCount; }

private:
LONG m_BusyCount;
};

The above CBusyTask class is safe for *Cooperative MultiTasking*
(cotask) implementations, such as within a GUI applications with
message events. If the busy actions are started by the a cotask
application, then the above is sufficient.

However, a more general CBusyTask that supports cotask and preemptive
multi-threads, then you need to support synchronization ideas. So
CBusyTask can be this now:

class CBusyTask {
public:
CBusyTask() : m_BusyCount(0) {}
void Clear() { InterlockedExchange(&m_BusyCount,0); }
LONG Enter() { return InterlockedIncrement(&m_BusyCount); }
LONG Exit() { return InterlockedDecrement(&m_BusyCount); }
BOOL IsBusy() { return m_BusyCount > 0; }
LONG Count() { return m_BusyCount; }
private:
LONG m_BusyCount;
};

So if these actions can occur from anywhere, it changes the
requirements for a "busy" flag.

If you add an CBusyTask m_Busy instance in your CWnd bsaed class or
make it global:

CBusyTask _g_Busy;

now in your OnTimer, it simplifies to this:

void CMyDialog::OnTimer(UINT nIDEvent)
{
if (nIDEvent == TIMER_IDENT) {
if (!_g_Busy.IsBusy()) {
check_for_transactions();
}
}
CMyDialog::OnTimer(nIDEvent);
}

You don't need an additional timer to wait. The CBusyTask will allow
you to keep a "reference count" of multiple actions either started in
a cooperating multi-tasking function or external multi-threaded
function that has access to the global _g_Busy.

As soon as all actions are done, the transaction checks can start with
no waiting.

All your actions will now just wrap the code of close with Enter() and
Exit() calls.

void CMyDialog::DoPrint()
{
_g_Busy.Enter();
... do printing ....
_g_Busy.Exit();
}

void CMyDialog::DoReport()
{
_g_Busy.Enter();
... do report ....
_g_Busy.Exit();
}

etc.

You can even get fancier, make it more robust and simplify coding of
not needing an explicit _g_Busy.Exit() call by using local scoping
ideas within your functions. So you can have something like this:

void CMyDialog::DoReport()
{

CBusyTaskGrabber grab(&_g_Busy);
... do report ....

if (whatever)
{
CBusyTaskGrabber grab(&_g_Busy);
... do whatever ...
} <--- Lost of Scope: grab instance destructor called

} <--- Lost of Scope: grab instance destructor called

where CBusyTaskGrabber is a wrapper class:

class CBusyTaskGrabber {
public:
CBusyTaskGrabber(CBusyTask *p) : pBusyTask(p) {pBusyTask->Enter();}
~CBusyTaskGrabber() {pBusyTask->Exit();}
private:
CBusyTask *pBusyTask;
};

that grabs a pointer to a CBusyTask instance to allow for automated
reference decrements upon the lost of local block scapes.

All the above was done quickly, and there many nits about it, the main
point is that solutions can vary depending on the question and
background cited. No background, people need to presume things about
what answer you are seeking.

--
HLS
From: Simon on

> Note that if this is a long computation in the main GUI thread, that you have not returned
> to the message pump, and consequently no timer messages could have been processed, and
> therefoere if the timer_is_complete flag was not set when you entered, it cannot be set
> when you leave.

It is not in the main GUI thread.

>
> And you should not compare a bool variable to a bool literal; this is poor style. What
> value to you think a bool variable has? And why aren't you just saying

This is your style, I don't agree with it.

> Well, Microsoft did not take your happiness into consideration.

Didn't ask for it.

>>
>> I could write my own timer class using a thread but this would add a lot
>> over testing overhead to the current app.
> ****
> Without a thread to do the work, the above code is pretty meaningless.

That does not mean anything.

Simon
From: Simon on
On 2010/04/30 04:13 PM, Joseph M. Newcomer wrote:
> I download NG posts, answer them over a period of many hours, and then download some more.
> Sometimes, there have been several answers since the original post or the most recent
> download. THere are people who think I have an "instantaneous view" of all posts by the
> time I make mine, but my collection might be six hours old, and I can only answer based on
> what I see, not what might have happened in the interim.

That's nice, thanks for sharing your NG habits.

Simon
From: Simon on
> ****
> ANd the answers were negative, which meant I couldn't really tell you what might work.

I was happy with the answers, (I started off by assuming it would not work).

> I get tired of trying to outguess what the
> question actually should have been, so I don't answer if I don't have specification of the
> problem.

Well then, don't try and throw in your 2p worth in every threads,
(especially if you don't know)

> Then I am very suspect of the design.

No, you are still making the wrong assumptions.

> But when the answers are "it is not possible" then we are left to guess about how the
> problem might be solved, and not knowing what the problem is means the guesses might be
> incorrect.

I know, others said it was not possible, (even I guessed it in my OP).
A discussion started on how a similar behaviour might be possible.

Read some of the replies, some very good suggestions were given.

> ... And there's a difference?

Yes there is. Sorry if you don't know the difference.

>
> "I need to know how much time has elapsed since I set a timer, because<problem
> description here>" and the answers are much easier to give.

Maybe with the school projects you work with.

Have a good week-end.

Simon
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8
Prev: _in s and _out s ?
Next: MSI Serial Number Validation