Prev: _in s and _out s ?
Next: MSI Serial Number Validation
From: Joseph M. Newcomer on 30 Apr 2010 10:19 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 30 Apr 2010 11:20 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 30 Apr 2010 11:35 > 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 30 Apr 2010 11:36 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 30 Apr 2010 11:42
> **** > 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 |