How to call SetWaitableTimerEx correctly - winapi

We have a long standing bug report in Boost.Thread where apparently thread sleeps will wake the computer from sleep on timer elapse (https://svn.boost.org/trac/boost/ticket/11368). This is apparently due to the new use of SetWaitableTimerEx() to implement coalescing timer support which we call with a REASON_CONTEXT like this:
REASON_CONTEXT default_reason_context={0/*POWER_REQUEST_CONTEXT_VERSION*/, 0x00000001/*POWER_REQUEST_CONTEXT_SIMPLE_STRING*/, (LPWSTR)L"generic"};
If timer firing is causing the PC to wake from sleep, it surely must have something to do with this REASON_CONTEXT value.
Can anyone here tell us what the appropriate value to use to not have the PC wake from sleep on timer expiry?

According to this document from Microsoft: Windows Timer Coalescing, page 8-9:
SetWaitableTimerEx has two new parameters: WakeContext and TolerableDelay. You use the WakeContext parameter only when you set a timer that can wake the system from a sleep state.
It looks like passing NULL for the WakeContext parameter is fine and it's the only way SetWaitableTimerEx will not wake the system. Timer coalescing should still work.
I tried it in Windows 10 and it seems to work correctly. It doesn't wake the system and also doesn't look like it's just calling SetWaitableTimer. It could be different in older versions of Windows though, I haven't tested.

Related

Does Windows will signal an event after wakeup?

Recently I met a problem that my program seems waiting for an event handle and never return.
I call IcmpSendEcho2 to send ping request and have set the event parameter correctly. In normal situation if the ping response arrived or timeout the event handle should be singled by system. This works fine in most time but one day I found my program (some of the working threads) is halt after my computer wakes up from sleep state. I guess the root cause is that when the ping request is sent and before system signal the corresponding event handle then the system change to sleep state (no operation for a long time then laptop change to sleep state). After system wakes up by me the previous event handle got no chance to be singled.
Add the pseudo code is:
// a working thread
while (isWorking()) {
...
IcmpSendEcho2(hIcmpFile, hEvent, NULL, NULL, ..., 5000/*timeout is 5 sec*/)
...
WaitForsingleObject(hEvent, INFINITE); // hEvent should be signaled after
// response arrived or timeout (5sec)
// elapsed
//
...
}
I don't know if I'm wrong. I'm still investigating on this problem and post this issue here hope somebody who has experience the same problem could help me. Thank you in advance!

Wait for download completion in FTP vb6

I have an Internet Transfer Control on a form called "inetFTP". After I call
inetFTP.Execute , "Get " & "test.zip" & " " & "C:/test.zip"
I want to pause the code execution until the download is finished, so there wouldn't be any other code operating on the file afterwards that could encounter problems. Is there a way to do that?
Normally you'd use the control's StateChanged event and monitor for at least the icError and icResponseCompleted states.
But in real programs it is often necessary to use this along with a Timer control and an elapsed time counter and cancellation flag. You'll want to be sure you don't miss any state changes (some don't seem to fire the event if they occur in quick succession), to handle timeouts, to cancel long running operations, etc.
I suspect there are some long standing bugs in the control that have never been ironed out, which is why StateChanged isn't as reliable as one might hope. Some of this may relate to inherent quirks or race conditions in the session-oriented FTP protocol. HTTP operations seem quite a bit more deterministic.
From there you'd need to change your program flow to properly fit the model of a Windows program.
A long running async operation can be started, but then there is only so much more "worth doing" in most cases until you get a completion signal (or an abort, etc.).
So you do that Execute and then exit the event handler you are running in. Once completion is signaled you resume processing in that completion event handler.
VB6 is not QBasic, and Windows is not DOS.
You can use a Timer (VBA.DateTime.Timer), see below:
Dim PauseTime As Single, start As Single
PauseTime = 2 ' pause the execution of code for two (2) seconds:
start = Timer
Do While Timer < start + PauseTime
DoEvents
Loop
I found the answer. I should insert
Do While inetFTP.StillExecuting
DoEvents
Loop
and this loops until the Internet Transfer Control finishes it job.

How to avoid full CPU utilisation, or terminate, while InternetOpenURL is trying (and failing) to connect?

I have a fairly simple application which downloads files in a thread. This thread uses the WinINet APIs, and begins like so:
HINTERNET hInternet = InternetOpen(strUserAgent.c_str(), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
DWORD dwFlags = INTERNET_FLAG_NO_UI | INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
HINTERNET hUrl = InternetOpenUrl(hInternet, m_strURL.c_str(), L"", 0, dwFlags, NULL);
However, if there is no internet connection, or the remote host is down, InternetOpenUrl will take a long time to time out and complete. While it is doing this - that is, only in the situation that it can't connect to the remote host - it will use between 80-100% of one CPU until it finally returns. This can often continue for a minute or so, because of the timeout delay setting. On one system, in spite of the timeout settings (noted below), this has continued for up to ten minutes.
How do I:
Avoid such massive CPU usage when it's just trying to connect?
Signal the thread to terminate if I want to shut down the app? Normally a timeout is fine, but if the app needs to close then it will wait on this thread to finish, which is spending lots of CPU doing very little inside InternetOpenUrl.
[Aside: Current timeout settings on my system, as revealed by InternetQueryOption:
INTERNET_OPTION_CONNECT_TIMEOUT: 60s
INTERNET_OPTION_RECEIVE_TIMEOUT: 30s
INTERNET_OPTION_SEND_TIMEOUT: 30s
Changing these would decrease the time before the method gave up and returned and so decrease the time spent using so much CPU, but might affect connecting - after all, the timeouts are there for a reason. This app can be used in odd connection situations, such as on board ship, where connecting could potentially be over satellite with high latency and take longer than a standard desktop internet connection. I do not know what reasonable timeouts would be. Also, there has to be a better method to avoid the CPU usage and terminate more quickly than simply shortening the timeouts.]
You can use WinInet in asynchronous mode. Not sure whether it solves CPU utilization issue but termination can be handled properly.
I think you can close the session handle returned from InternetOpen with InternetCloseHandle.
According to http://msdn.microsoft.com/en-us/library/aa384350(v=VS.85).aspx it will unblock any pending operation on that handle.
So basically if you keep InternetOpenUrl in a separate thread, you can still close the session handle from the parent thread(a seperate thread is not required if you are using it in async mode). You can set a status callback function for any resource cleanup.
If you want to set a different timeout, use InternetSetOption.
PS: Its been a while I've done anything with WinINet library, so I cannot guarantee that the above method will work.

How to detect inactive user

How to detect inactive (idle) user in Windows application? I'd like to shutdown application when there hasn't been any input (keyboard, mouse) from user for certain period of time.
To track a user's idle time you could hook keyboard and mouse activity. Note, however, that installing a system-wide message hook is a very invasive thing to do and should be avoided if possible, since it will require your hook DLL to be loaded into all processes.
Another solution is to use the GetLastInputInfo API function (if your application is running on Win2000 (and up) machines).
GetLastInputInfo retrieves the time (in milliseconds) of the last input event (when the last detected user activity has been received, be it from keyboard or mouse).
Here's a simple example. The SecondsIdle function returns a number of second with no user activity (called in an OnTimer event of a TTimer component).
~~~~~~~~~~~~~~~~~~~~~~~~~
function SecondsIdle: DWord;
var
liInfo: TLastInputInfo;
begin
liInfo.cbSize := SizeOf(TLastInputInfo) ;
GetLastInputInfo(liInfo) ;
Result := (GetTickCount - liInfo.dwTime) DIV 1000;
end;
procedure TForm1.Timer1Timer(Sender: TObject) ;
begin
Caption := Format('System IDLE last %d seconds', [SecondsIdle]) ;
end;
http://delphi.about.com/od/adptips2004/a/bltip1104_4.htm
You might want to see the answer to this question: How to tell when Windows is inactive [1] it is basically same question the solution suggested is to use the GetLastInputInfo [2] API call.
This post explains some aspects as well: (The Code Project) How to check for user inactivity with and without platform invokes in C# [3]
[1] How to tell when Windows is inactive
[2] http://msdn.microsoft.com/en-us/library/ms646302%28VS.85%29.aspx
[3] http://www.codeproject.com/KB/cs/uim.aspx
Your application will get a WM_SYSCOMMAND message with SC_SCREENSAVE as a command id when the Screen Saver is about to kick in. Would that do? there's also the SC_MONITORPOWER command id when the monitor is about to blank (also a WM_SYSCOMMAND message).
Edit: looking at the comments, it appears that you don't care about whether the user is inative, but rather whether your application is inactive.
This is easy. If your app is minimized, then the user isn't interacting with it. If your app is not the foreground application, that's a good inicator as well.
You could also pay attention to messages in your pump to notice if there have been any user input messages to your app, In C++ adding code to the pump is trivial, in delphi you can use a WH_GETMESSAGE hook to monitor the pump hook into the message loop that TApplication implements. Or GetLastInputInfo
This SecondsIdle doens't work at all.
The way is to use a TTimer combined with a second variable that resets every time user inputs mouse or keyboard.

Timer Queues, immediately terminate a timer?

I'm trying to achieve high frame-per-second on Windows GDI by using Windows Timer Queues. The relevant APIs are CreateTimerQueue, DeleteTimerQueueEx, CreateTimerQueueTimer, and DeleteTimerQueueTimer .
The timer is created using CreateTimerQueueTimer(&m_timer, m_timer_queue, TimerCallback, this, 0, 20, WT_EXECUTEINTIMERTHREAD); to achieve some 50fps of speed. GDI operations (some painting in the backstore, plus InvalidateRect) cannot be asynchronous, therefore I can't choose other flags but WT_EXECUTEINTIMERTHREAD so that no extra sync op is required on the drawing code. The idea is to achieve 50fps when possible, and when it's not, just show each frame at the maximum possible speed.
At the end of the animation (reached a total frame count), DeleteTimerQueueTimer is called to destroy the timer.
The problem is that DeleteTimerQueueTimer doesn't immediately turn off the callings of the callback function. When it's not possible to achieve the 50fps requirement, the timer pumps the call into a queue. Calling DeleteTimerQueueTimer inside the callback function doesn't destroy the queue. As a result, the callback is still being called even though it decided to shutdown the timer.
How do I deal with this problem?
-
On another note, the old timeSetEvent / timeKillEvent multimedia API doesn't seem to have this problem. There are no queues and the calling of the callback function is immediately stopped when I call timeKillEvent. Is it possible to achieve the same behavior with timer queues?
You can pass the WT_EXECUTEONLYONCE flag to the CreateTimerQueueTimer function. This will cause the timer to trigger only once and not periodically.
You can then reschedule the timer with the ChangeTimerQueueTimer method.
To cover the times where your drawing takes too long too complete in the frame, you can add a CriticalSection to the beginning of the TimerHandler method, which will cause the 2nd timer to wait until the first one completes.
If you want to run something at 50fps+, you'd probably do better to actually just have a draw loop which computes the amount of time between frames and scales the animation accordingly. Timers aren't really meant to fire so often. So (and this would probably be in your Idle handler). Like, this pseudocode (ignore lack of error handling):
static longlong last_frame;
while(1) {
longlong current_frame = QueryPerformanceCounter();
long delta = current_frame - last_frame;
// Do drawing here, scale amount to move by how much time has elapsed
last_frame = current_frame;
}
DeleteTimerQueueTimer will cancel the timer provided it has not already been scheduled. (When you use WT_EXECUTEINTIMERTHREAD I believe they are queued as an APC on a thread from a thread pool shared by the timer queues and worker threads. ) If it has already been scheduled (not just running) - it will be run and the DeleteTimerQueueTimer call will block until completion.
If I understand your problem correctly, may I suggest the following?
1. Before calling DeleteTimerQueueTimer - set a flag say abortAllTimers to true.
2. In each timer call back function check to see if abortAllTimers is true. If it is true - then return at once without doing any drawing.
And finally - DeleteTimerQueueTimer should not be called from the timer callback. Instead I would suggest you should call it from any other thread - say the thread you used to start the timers.
Hope this helps.

Resources