Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Scheduling Operations by time in MFC 1

Status
Not open for further replies.

thebarslider

Programmer
Dec 21, 2001
80
GB

Hey everyone,

I'm having problems understanding how to schedule program operations in C++ using MFC.

I have developed a program that records from the radio using a radiocard.
I wish to set up a scheduler that will record radio programmes at a given time.
So far i have developed a Programme class that will be used to store the information. Time frequency etc.
I wish to create many different programme objects but they must reference each other (so that the recording times don't overlap) and can also reference the current time in order to determine whether recording should start.

Does anyone have any ideas where i should start? Do i need to create objects at run-time and then somehow get pointers to them? Or would it be easier to store the information in a file/structure then parse this to determine whether recording should start.

Any suggestions would be much appreciated.

Mark.
 
Mark,

You asked many questions in your post. I will address how to schedule program operations. Then after you research that issue perhaps you will ask some of the other questions again, but with a more concrete context, making them easier to answer.

On Windows NT/98/ME OS you can use the Waitable Timer API’s to schedule your own programs operations. On Windows 2000 and XP you can use the new kernel 5 TimerQueue API’s to schedule operations which is more efficient.

To research these API’s see CreateWaitableTimer() and CreateTimerQueue() in the Platform SDK.

does that help?
-pete
 

Dear Pete,

Firstly i wish to thank you for your geneous help, both in this thread and in the past.

I have researched the API's you mentioned above and i think you may have mis-understood what i was attempting to do.

All i simply want to do is execute some code a give time. It is not repetitive execution simply to execute at one time. For example: the time is 5pm - so start recording.

I have a programme object that stores the time to start recording and i simply need to access the current time and execute the code when necessary.

My current thinking is to write the information to a .dat file then parse this using a thread to verify whether recording needs to take place at the current time.

Mark.
 
Mark,

After reading you second post, I still think i gave you the correct direction. I have used the Waitable Timers to do precisely what you describe. I have not use the newer Timer Queue for that purpose but I believe it also has that capability.

The second parameter of SetWaitableTimer can be used to set the “exact” time that you want the event to occur. It does not need to be “repeating”.

hope that helps
-pete
 
Hey Pete,

After more research i understand what to do now, thank you again for your help.

The only problem i have now is understanding the timer completion routine. Can i simply declare a function of type PTIMERAPCROUTINE in my class and then simply input the code that i want to execute? Do i have to override TimerAPCProc?

Thank you very much for your help.

P.S. How do i give you a tip master vote?

Mark.
 
Mark,

Since you do an active block (WaitForSingleObject) on the timer using the Waitable Timer mechanism you only need to define the completion routine if you desire to be notified of that event. In my case i did not have any processing that required notification of that event so i used NULL for that parameter.

There are links at the bottom of each post for interacting with the administrative operations of Tek-Tips.

glad you are making progress.
-pete


 
Dear Pete,

I have used the WaitForSingleObject function in a CWinThread* but the method still doesnt seem to be called when returning WAIT_OBJECT_0. It appears that i need to assign SYNCHRONIZE access to the CreateWaitable handle.

As stated on MSDN:


As i am using Windows XP.

I am unsure how to do this and dont understand how i can set this value to SYNCHRONIZE.

Hope you can help.

Mark.
 
>> but the method still doesnt seem to be called when
>> returning WAIT_OBJECT_0

What method does not get called? I don't understand your post.

When i create a waitable timer like this:

Code:
_hTimer = ::CreateWaitableTimer( NULL, true, NULL);

Then set it like this
Code:
::SetWaitableTimer(_hTimer, &dueTime, lPeriod, NULL, NULL, true);

And Wait for it like this
Code:
::WaitForSingleObject( _hTimer, INFINITE);

and it returns WAIT_OBJECT_O i know that the timer was signaled and i do whatever i need to since it is "time".

-pete
 
Okay i understand what you are saying, but where do you place the code you wish to excute when it is "time" for example: The "time is right to record" i.e. 4pm for therefore call the record start method:

NewRecorder.Record();

I dont understand where you have to place this code. So far i have this function:

if (WaitForSingleObject(WaitableTimerHandle,INFINITE) == WAIT_OBJECT_0 )
{
TRACE("WAITABLE TIMER SIGNALLED\n");

return(0);
}

This is inside a UINT TimerCheckFunc function that is run by a thread.
The TRACE doesnt ever seem to be called even when it is time. I feel this is because the security attribute has not been set to SYNCHONIZE but i dont know how to set this variable.

Mark.
 
>> I feel this is because the security attribute has not
>> been set to SYNCHONIZE

Mark, i don't know what that means. Be more explicit.

If your is not signaled when you expect it to i would suspect the value you send to ::SetWaitableTimer()

-pete
 
In the context of the first parameter of WaitForSingleObject:

hHandle
[in] Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section.
If this handle is closed while the wait is still pending, the function's behavior is undefined.

Windows NT/2000/XP: The handle must have SYNCHRONIZE access. For more information, see Standard Access Rights.

I'm quite sure that the &dueTime value in SetWaitableTimer is correct as i set it up using:

pSystemTime.wYear = 2003;
pSystemTime.wMonth = 3;
pSystemTime.wDay = 31;
pSystemTime.wHour = 3;
pSystemTime.wMinute = 10;

Then converted it to file time using:

SystemTimeToFileTime(&pSystemTime,&pFileTime);

I have check that this works using the debugger.

Is correct or is it that the second parameter of SetWaitableTimer should be the value from when the timer was set to when the timer should activate rather than the absolute time (i.e. nanoseconds since 1600 that is given by the SystemTimeToFileTime conversion.

Mark
 
Mark said,

I'm quite sure that the &dueTime value in SetWaitableTimer is correct as i set it up using:

pSystemTime.wYear = 2003;
pSystemTime.wMonth = 3;
pSystemTime.wDay = 31;
pSystemTime.wHour = 3;
pSystemTime.wMinute = 10;

Then converted it to file time using:

SystemTimeToFileTime(&pSystemTime,&pFileTime);


So your sending what to the SetWaitableTimer() function as the second parameter, pFileTime?

That is not going to work.

-pete
 
I'm sending SetWaitableTimer a pointer to filetime that is declared as:

_SYSTEMTIME pSystemTime;
_FILETIME pFileTime;

My code is:

SystemTimeToFileTime(&pSystemTime,&pFileTime);

if ( SetWaitableTimer(_hTimer,(LARGE_INTEGER*) &pFileTime, 0,NULL,NULL,NULL) == 0 ) {
TRACE ("---- SetWaitableFailed ----\n");
}

I use the return value of SetWaitableTimer to check for an error.

If this cannot work, how else can i set the time for SetWaitableTimer?

Mark.
 
You did not convert your FileTime to UTC. From the SDK:

Be sure to use a UTC-based absolute time, as the system uses UTC-based time internally.

-pete
 
I am based in the UK and am using GMT for my system time.

I have also tested functions such as:
UINT TimerCheckFunc ( LPVOID pParam )
{
while ( !(pSystemTime.wMinute == systemnow.wMinute )) {

GetSystemTime(&systemnow);
TRACE(" $$$$$ The time is NOT now $$$$$\n ");

}
return(0);
}

To attempt to trace catch the "time is up" in my thread. But to no avail.

I am unsure what i am doing wrong.

Is there any other method of checking against time using a thread in windows.

Thanks again for your generous help.

Mark.
 
Mark,

I am at a loss. I just ran my old unit test app where I test the classes i built that use the functions we discussed and it works as i had remembered.

of course I am make the call to ::LocalFileTimeToFileTime()

good luck
-pete

 
Dear Pete,

Could i just ask what operating system you are using and what type of thread you are calling WaitForSingleObject() in. Mine is of type:

CWinThread* pWAVThread = AfxBeginThread

Also if possible could you email me the example code if possible. My email address is: thebarslider@hotmail.com

I know i'm asking for a lot here but hopefully i'll be able to pass on my knowledge to other people in the future.

Thanks again for helping me. You have helped me lots in previous posts.

Mark.
 
Hey Pete,

I've found my mistake after some further research in my program and now understand how the function works and have got it to function within my program.

Thanks alot of your help.

Mark.
 
Mark,

The unit test project i will send you was originally developed and unit tested on NT 4 workstation VC++ 6. The production project which is a NT Service was originally deployed on NT 4 Server. The product is currently running on Windows 2000 Server. My workstation i am currently building and running the unit test app on is Windows 2000 professional.

I will zip the unit test project and email it to you. It is an MFC dialog application. The final notification of the thread timeout being signaled is not displayed in the UI but only TRACE()ed since i was not motivated to develop the cross thread UI messaging for the unit test application.

-pete
 
Glad you have it working Mark!

I saw your message before i sent the email.

-pete
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top