This question already has answers here:
Can I use a SetTimer() API in a console C++ application?
(6 answers)
Closed 9 years ago.
I have below program. I would like to know how setTimer works. So, I wrote a program but could not able to understand why TimerProc function not getting called. Why? What else need to be done to fire setTimer/TimerProc. Please help.
#include <windows.h>
#include <stdio.h>
VOID CALLBACK TimerProc(
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime // current system time
) {
printf("from callback\n");
}
int main(int argc, char *argv[])
{
UINT timerid = SetTimer(NULL,1,1000,TimerProc);/*changed the time from 1 to 1000, but no effect*/
printf("timerid %d\n",timerid);
int i,j;
//delay loop, waiting for the callback function to be called
for(j=0;j<0xffffffff;j++);
/*{
printf("%d\n", j);
}*/
printf("done \n");
system("PAUSE");
return 0;
}
The timer works via a Windows message queue and you have a console application.
If you create a basic Win32 application so you get a window and a message loop, when the WM_TIMER message is caught by the DefWndProc() call, that's where it will do the callback. Of course you can also trap the WM_TIMER yourself.
The SetTimer documentation says:
*When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.*
Instead the delay loop you need something like:
bool bStillBusy = false;
int main()
{
MSG msg;
bStillBusy = true;
id = SetTimer(NULL, 0, 3000, (TIMERPROC) TimerProc);
while(bStillBusy)
{
GetMessage(&msg, NULL, 0, 0);
DispatchMessage(&msg);
}
...
etc.
}
You set the bStillBusy to 'false' in the callback then.
You need to learn the message loop paradigm. You are trying to use Win32 api without actually doing the right Win32 initialization and operations.
If you come from Posix, you'd could use a SIGALRM and alarm.
On windows, I'm afraid you'll have more work to do (like starting a message loop, because even when you provide a callback function, you need a message loop pumping that's calling the default message loop processing function will call your timer's callback, check this:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx
An application can process WM_TIMER messages by including a WM_TIMER case statement in the
window procedure or by specifying a TimerProc callback function when creating the timer.
When you specify a TimerProc callback function, the default window procedure calls the
callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in
the calling thread, even when you use TimerProc instead of processing WM_TIMER.
Timer are handled using the normal Windows event system, so you need a normal event loop.
Related
I'm creating a thread for my game. But I found, that if close button is pressed, or the task is killed I cannot properly finish the work, deallocating all the resources I needed inside the program.
I found that Close handler exists, but the example given is an unknown magic to me, because I need to create something similar in ANSI-C.
static BOOL CloseHandler(DWORD evt)
{
if (evt == CTRL_CLOSE_EVENT)
{
m_bAtomActive = false;
// Wait for thread to be exited
std::unique_lock<std::mutex> ul(m_muxGame);
m_cvGameFinished.wait(ul);
}
return true;
}
I know that Winapi has Mutex and conditional variables, but I do not know anything about std::atomic equivalent.
I have this thread start function and inside thread function GameThread I have a regular bool variable m_bAtomActive checked now.
void Start(void* _self)
{
DWORD dwThreadID;
HANDLE hThread;
struct c_class* this = _self;
this->m_bAtomActive = true;
hThread = CreateThread(
NULL,
0,
&GameThread,
_self,
0,
&dwThreadID);
WaitForSingleObject(hThread, INFINITE);
}
I'm bad at threading, what should I do to properly finish the work of my game?
All the additional details will be provided in the comments or on the chat.
UPD: The first thing seems to be easy, it is solvable with this line inside close handler
if(Active)
InterlockedDecrement(&Active);
But the second and third is still under question. They might be created for the reason of CloseHandler killing the app before destruction, but I don't know for sure.
I'm writing a C program.
For thread I use the WINAPI library.
But sometimes the CreateThread function don't launch the function associate.
I used the WaitForSingleObject function with INFINITE param to let my thread start but he never start
The GetLastError functions return always 0,so I don't know where is my mistake
The merge function is call when GTK button is press.
Below you will find my code
void merge(GtkWidget *wiget, gpointer data){
HANDLE thread;
FtpLogin *login = (FtpLogin *) data;
thread = CreateThread(NULL, 0, mergeThread, login, 0, NULL);
printf("%ld", GetLastError());
WaitForSingleObject(thread, INFINITE);
if(thread == NULL)
puts("error");
}
DWORD WINAPI mergeThread( LPVOID lpParam )
{
puts("Thread start");
return 0;
}
Thanks for your help
The C run-time library needs some per-thread initialization. CreateThread(), which knows nothing about the C RTL, doesn't perform that.
Instead of CreateThread(), use _beginthreadex(). It's declared in <process.h>.
According to this page, GTK is not thread safe. Anything that interacts with the GUI inside your mergeThread function can have unexpected results.
Please refer to the link I provided for more information about multithreaded GTK applications to see how to use GDK instead.
I'm trying to write a simple UDP transfer program in Labwindows/CVI.
The idea is it creates 2 UDP channels, uses one to write data to a port, and the other to receive the data and print it out.
Here's the receiving end:
//Called whenever data arrives on port
int CVICALLBACK udpCallback(unsigned channel, int eventType, int errCode, void *callbackData)
{
printf("Callback called\n");
//Gets the data from port
readChannel();
return 0;
}
void createReadChannel()
{
//Channel for given port, receiving from any IP address
CreateUDPChannelConfig(port, UDP_ANY_ADDRESS, 0, NULL, NULL, &readerChannel);
//Attach callback to channel (above)
SetUDPAttribute(readerChannel, ATTR_UDP_CALLBACK, udpCallback);
printf("Read channel created\n");
}
My main problem is just that when I run it in debug mode, the shown callback function is never called, i.e. "Callback called" is not printed, not is any data stored or printed in the resulting readChannel() call.
However, when compiled and executed as an .exe, it works as intended. Every time data is received on that port the callback executes.
What difference could there be between the debug and 'release' version that would cause this to happen?
EDIT: After much testing I believe it has to do with waiting for messages using functions like getchar() which caused the main thread to hang up. Why it worked in release mode I don't know, but it probably has something to do with the difference in output window(?). My solution was to remove the callbacks and run the receiving channel on it's own thread.
This way the thread is always waiting for a message, using:
UDPRead(readerChannel, 0, 0, UDP_WAIT_FOREVER, NULL, NULL)) < 0)
And then my main thread can pick up messages as needed.
If anyone has any additional info let me know.
I am encoutering a issues with win32 programming doing a serial port communication using a event-driven approach. I have my communication handle created as:
hComm = CreateFile(lpszCommName, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, NULL);
and i set my CommTimeouts as:
commTimeout.ReadIntervalTimeout = MAXWORD;
commTimeout.ReadTotalTimeoutConstant = 0;
commTimeout.ReadTotalTimeoutMultiplier = 0;
commTimeout.WriteTotalTimeoutConstant = 0;
commTimeout.WriteTotalTimeoutMultiplier = 0;
I created a thread for ReadFile which looks like this:
SetCommMask(hComm, EV_RXCHAR);
while (isConnected)
{
if (WaitCommEvent(hComm, &dwEvent, NULL)) //If i comment out this block my write file will work fine
{
ClearCommError(hComm, &dwError, &cs);
if ((dwEvent & EV_RXCHAR) && cs.cbInQue)
{
if (!ReadFile(hComm, str, cs.cbInQue, &read_byte, NULL))
/* Process error*/
else if (read_byte)
/* Print to screen */
}
else {
/* Process error*/
}
}
}
PurgeComm(hComm, PURGE_RXCLEAR);
My Wrifile goes into WndProc which sends characters to the communication device when WM_CHAR is triggered:
VOID Write_To_Serial(WPARAM wParam, HWND hwnd){
DWORD write_byte;
char str[10];
sprintf_s(str, "%c", (char)wParam); //Convert wParam to a string
WriteFile(hComm, str, strlen(str), &write_byte, NULL)//Program hangs here
}
My problem is everytime WriteFile() is called my application hangs and I have to force to close it. And if I comment out the WaitCommEvent() in my read thread it works fine, but I can't read then.Any pointers would be appreciated. thanks
This is the expected behavior of Synchronous IO operations.
As per the following description in Serial Communications article in MSDN (https://msdn.microsoft.com/en-us/library/ff802693.aspx),
It is the responsibility of the application to serialize access to the
port correctly. If one thread is blocked waiting for its I/O operation
to complete, all other threads that subsequently call a communications
API will be blocked until the original operation completes. For
instance, if one thread were waiting for a ReadFile function to
return, any other thread that issued a WriteFile function would be
blocked.
WriteFile has to wait until WaitCommEvent function has completed its operation.
A small workaround would be to cancel the pending WaitCommEvent operation (for instance by using CancelIoEx API) when WriteFile needs to be invoked.
VOID Write_To_Serial(WPARAM wParam, HWND hwnd){
DWORD write_byte;
char str[10];
sprintf_s(str, "%c", (char)wParam); //Convert wParam to a string
CancelIoEx(hComm, NULL);
WriteFile(hComm, str, strlen(str), &write_byte, NULL);//Program hangs here
}
WaitCommEvent returns FALSE when canceled. Hence,the code following WaitCommEvent will not be executed.
However, in extreme case, there is a chance, where the thread invoking the ReadFile function, re invokes the WaitCommEvent function, before WndProc gets to WriteFile. If this occurs, it needs to be handled separately. Maybe a small delay when WaitCommEvent returns FALSE would do.
I'm building some FastCGI apps and it sort of bugs me that lighttpd doesn't kill them off after they've been idle, so I'm trying to have them close on their own.
I tried using
signal(SIGALRM, close);
alarm(300);
and having the close function execute exit(0), and that works almost well.
The problem is the close function is being called every time the main program loop runs though (I call alarm(300) each loop to reset it). I've read the man page for alarm() and it doesn't seem as though calling it multiple times with the same value should trip SIGALRM so I'm assuming Lighttpd is sending an alarm signal.
The big question! Is there a way to run a method after a specific interval, and have that interval be resettable without SIGALRM? I'd be nice if I could have multiple alarms as well.
Here's the whole app thus far:
#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>
#include "fcgiapp.h"
FCGX_Stream *in, *out, *err;
FCGX_ParamArray envp;
int calls = 0;
void print(char*, ...);
void close();
int main(void)
{
// If I'm not used for five minutes, leave
signal(SIGALRM, close);
int reqCount = 0;
while (FCGX_Accept(&in, &out, &err, &envp) >= 0)
{
print("Content-type: text/plain\r\n\r\n");
int i = 0;
char **elements = envp;
print("Environment:\n");
while (elements[i])
print("\t%s\n", elements[i++]);
print("\n\nDone. Have served %d requests", ++reqCount);
print("\nFor some reason, close was called %d times", calls);
alarm(300);
}
return 0;
}
void print(char *strFormat, ...)
{
va_list args;
va_start(args, strFormat);
FCGX_VFPrintF(out, strFormat, args);
va_end(args);
}
void close()
{
calls++;
// exit(0);
}
the best way is: add a thread so that you can remove signal and alarm, and sync the thread and your main code (main thread).
I'd probably use POSIX timers. Timers do not have to use signals. You have a choice between not notifying at all, raising a signal, or running a function as a new thread (which I would do as it will not interfere with fastcgi).
Make sure you include <signal.h> and <time.h>, and link with -lrt
First, I'd fill out your sigevent structure:
struct sigevent myTimerSignal = {
.sigev_notify = SIGEV_THREAD,
.sigev_notify_function = close //Make sure you change your function declaration to close(union sigval), you do not need to use the sigval unless you store data in your event too
};
Now create your timer:
timer_t myTimer;
if(timer_create(CLOCK_REALTIME, &myTimerSignal, &myTimer)){
//An error occurred, handle it
}
Lets arm it, it will call close() in a new thread in 300 seconds:
struct itimerspec timeUntilClose = {
.it_value = {
.tv_sec = 300 //300 seconds
}
};
if(timer_settime(myTimer, 0, &timeUntilClose, NULL)){
//Handle the error
}
Now, you should have a timer ready to stop the program after 300 seconds. I know I may be late, but I hope this helps a future reader.
Maybe you can wrap the close function by another function which will first call sleep()?
The argument to the alarm call is seconds, not minutes. So you're asking to be woken up in 5 seconds after each time through the main loop.
Here's a solution that sort of avoids the point of the question, but it works. It will respond to only my application's signal events:
void close(int intSignal, siginfo_t *info, void *context)
{
// For some stupid reason MY signal doesn't populate siginfo_t
if (!info)
{
count++;
}
}
If the siginfo struct is empty, that's because alarm() tripped it. If an outside process does it, siginfo_t.si_pid is populated with zero.
I still don't like this solution, but it works. Odd problem now is that doing an exit(0) doesn't close the application, though lighttpd thinks it's gone and spawns another. This means that now I've got rouge processes. raise(SIGUSR1) which is what is supposed to stop FastCGI scripts doesn't seem to do the trick either... hmmm...
Question still remains: How does one call asynchronous functions on an interval timer without the use of signals?
Try to close all the file descriptors (including stdin and stdout). This should close the CGI instance if its idle.
You can use select() with timeout to schedule instead of SIGALRM