Asynchronous usage of RegNotifyChangeKeyValue is simple enough: pass it an event object and wait for the event to be signalled.
What is not so clear, however, is the correct way to cancel a notification request. For example, if a timeout has been set on the wait like so:
RegNotifyChangeKeyValue(hKey, false, REG_NOTIFY_CHANGE_LAST_SET, regEvent.SafeWaitHandle, true);
regEvent.WaitOne(TimeSpan.FromMinutes(30))
If the timeout occurs without the notify firing, this notification is left presumably pending and waiting to fire. This is worse if the notify and wait is within a loop, potentially registering many notifications (one for each expired timeout).
Do I simply close both the event handle (regEvent) and the registry key handle (hKey)? Is there anything else I need to call, e.g. directory change notifications have FindCloseChangeNotification, is there an equivalent here?
I'm currently using P/Invoke with C#, but I do not believe that should make a difference - any answer should be focused on the requirements and usage of the Windows API. This would be much the same question if I had used RegNotifyChangeKeyValue/CreateEvent/WaitForSingleObject from VC++.
Closing the open Registry key is enough. When the key is closed, the event is signaled. This is documented behavior. So, simply be sure to close the Registry key before freeing the event.
Related
An asynchronous call to ReadDirectoryChangesW() can be cancelled by the CancelIo() function. However, by the time CancelIo() has been called, the notification buffer associated with ReadDirectoryChangesW() may be half filled in. The question is, what happens with those notifications? Should they be processed in a normal way?
More specifically, I issued an overlapped ReadDirectoryChangesW() command with a completion routine, and than cancelled it by means of CancelIo(). When my completion routine is called with an ERROR_OPERATION_ABORTED error, should I still check the notification buffer for possible notifications?
Clarification:
My File System Listener component successfully serves for my company already more than ten years. Now I'm going to modify the component in order to implement a more sophisticated monitoring policy. With this policy, cancelling a particular ReadDirectoryChangesW() request doesn't mean cancelling of monitoring, and I do not want to miss even a single notification.
OK, I found experimentally that the second parameter of completion routine (dwNumberOfBytesTransfered) in the case of ReadDirecoryChangesW() function contains number of bytes written to notification buffer. Unfortunately, I didn't find a clear confirmation of that in documentation.
However, this hypothesis seems reasonable, and if it is always true, I can conclude about presence of notifications by checking of that parameter regardless of the completion routine's first parameter (dwErrorCode). This solves the problem.
I am implementing a Reactor design pattern, using a single thread, for asynchronous operations using Windows Events Mechanism.
I faced a problem while trying to combine my reactor to support Windows Notifications (WM_CLOSE, WM_CREATE, WM_DEVICECHANGE...) along with the existing Windows Events.
Thus, my question is:
Is it possible to signal an event when a particular window receives a particular notification?
Thanks in advance.
No, you cannot make Windows signal an event object when particular window messages are received. You would have to catch the messages in your message loop first and then signal the event object yourself as needed.
Otherwise, re-write your message loop to use MsgWaitForMultipleObjects() so it can check for event signals and pending window messages at the same time, and then you can act according to whichever one satisfies the wait on each loop iteration. Just be aware of this gotcha:
MsgWaitForMultipleObjects is a very tricky API
if you specify bWaitAll as true, you may find that your application doesn’t wake up when you expected it to
In this situation, you would set bWaitAll to false and all is well.
I have a class that implements a file-monitoring service to detect when a file I am interested in has been changed by something other than my application. I use the standard technique of opening the file (with the O_EVTONLY flag) and binding the file descriptor to a Grand Central Dispatch source of type DISPATCH_SOURCE_TYPE_VNODE. When I get an event, I notify my main thread with NSNotificationCenter's postNotificationName:object:userInfo: which calls an observer in my app delegate. So far so good. It works great. But, in general, if the triggering event is an attributes change (i.e. the DISPATCH_VNODE_ATTRIB flag is set on return from dispatch_source_get_data()) then I usually get two closely-spaced events. The behaviour is easily exhibited if I touch(1) the object I am monitoring. I hypothesise this is due to the file's mtime and atime being set non-atomically although I can't verify this. This can lead to spurious notifications being sent to my observer and this raises the possibility of race conditions etc.
What is the best way of dealing with this? I thought of storing a timestamp for the last event received and only sending a notification if the current event is later than this timestamp by some amount (a few tens of milliseconds?) Does this sound like a reasonable solution?
You can't ever escape the "race condition" in this situation, because the notification of your GCD event source in your process is not synchronous with the other process's modification of the underlying file. So, no matter what, you must always be tolerant of the possibility that the change you're being notified for could already be "gone."
As for coalescing, do whatever makes sense for your app. There are two obvious strategies. You can act immediately on a received event, and then drop subsequent events received in some time window on the floor, or you can delay every event for some time period during which you will drop other events for the same file on the floor. It really just depends on what's more important, acting quickly, or having a higher likelihood of a quiescent state (knowing that you can never be sure things are quiescent.)
The only thing I would add is to suggest that you do all your coalescence before dispatching anything to the main thread. The main thread has things like tracking loops, etc that will make it harder to get time-based coalescing right in certain cases.
I'm trying to implement user threads on a 2.4 Linux kernel (homework) and the trick for context switch seems to be using an alarm that goes off every x milliseconds and sends us to an alarm handler from which we can longjmp to the next thread. What I'm having difficulties with is figuring out how to save the environment to return to later.
Basically I have an array of jmp_buffs, and every time a "context switch" using the alarm happens I want to save the previous context to the appropriate entry of the array and longjmp to the next one. However, just the fact that I need to do this from the event handler means that just using setjmp in the event handler won't give me exactly the kind of environment I want (as far as stack and program counter are involved) because the stack has the event handler call in it and the pc is in the event handler.
I suppose I can look at the stack and alter it to fit my needs, but that feels a bit cumbersome. Another idea I had is to somehow pass the environment before the jump to event handler as a parameter to the event handler, but I can't figure out if this is possible.
So I guess my question is- how do I do this right?
You should be able to just do something like:
if (setjmp(&from_thread))
return;
else
longjmp(&dest_thread, 1);
in the event handler. Sure, it means it'll arrive back in the thread in the event handler - but that's OK because then you'll return straight out of it, so it'll go back to where the thread was when the event handler triggered.
(Of course this presumes that you've set up separate stacks for the threads already).
I wish to launch a separate thread for handling window messages (via a blocking GetMessage loop), but still create the windows in the initial thread, afterward.
Within the separate thread, as soon as it launches, I am calling PeekMessage with PM_NOREMOVE to ensure a message queue exists (is this necessary?), followed by..
AttachThreadInput(initial thread id,GetCurrentThreadId(),true)
..before finally entering the message loop
I am not yet using a mutex or cs to ensure this is happening in time, but am merely using a Sleep statement in my initial thread for the sake of simplicity.
Regardless, window messages do not appear to be intercepted by the separate thread.
I am a little unsure as to whether I am doing this correctly, and would appreciate any possible guidance. Both threads are in the same process
Thank you all
That's not what AttachThreadInput does. Even after you attach your input queue to another thread, Windows still have thread affinity. Messages in the queue for a given window can only be removed from the queue by that window's thread.
What AttachTheadInput does is to make two threads share an input queue. This allows them to query information about the input state and know that the other thread will get the same answer for the same query. For instance, one thread could call GetAsyncKeyState and know that the answer reflected the key state for the other thread.
It allows two or more threads to have the same relationship to the input queue and each other as processes had in Windows 3x. This is the reason that this API exists; so that complex multiprocess applications could be ported from Win 3x to Win95/WinNT.
It seems the best way to instigate window creation from the main thread, while having messages for them handled in a separate, looping thread is to use a custom message, that can be sent to the separate thread - Thus allowing it to create the window, but still allowing that action to be invoked from the initial thread:
1) Allocate a custom message, and create a structure to hold the window initialisation parameters:
message_create_window = WM_USER + 0;
class Message_create_window{
Message_create_window(...);
};
2) Instead of calling CreateWindow(Ex), use something similiar to the following, passing in the relavant window creation parameters:
PostThreadMessage(
thread.id,
message_create_window,
new Message_create_window(...),
0
);
3) Handle the custom message in the message pump of your ui handling thread, extract the creation parameters, & free afterwards:
MSG msg;
GetMessage(&msg,0,0,0);
...
switch(msg->message){
...
case message_create_window:{
Message_create_window *data=msg->wParam;
CreateWindowEx(data->...);
delete data;
}break;
...
This does, however, have the following side-effects:
The window will be created asynchronously. If it is required that the initial thread block until the window is created (or, indeed, that the window's existence can ever be asserted) then a thread synchronisation tool must be used (such as an event)
Care should be taken when interacting with the window (it is a multithreaded application, after all)
If there are any major holes in this answer, or this seems like a terrible approach, please correct me.
(This is still my question, & I am trying to find the best way to accomplish this)