I have a library that needs to call the main windows thread in UWP when it receives a message from a communication channel (let say, a message indicating a check box should be checked). The library saves a copy of the SynchronizationContext when it starts up, so it can Post back to it when the data comes in, but the trouble is, I'm not guaranteed that the caller of this library is on the main thread when it's initialized.
Is there some simple, guaranteed way to obtain the Main Window Thread (that is, the Windows' SynchronizationContext) so I don't need to rely on the caller to make sure the contexts aren't switch?
Trying to push something onto "the main window thread" will fail eventually when you pick the wrong window / thread. A better design is to have the library expose an event and then any consumer (including the main window) can listen to that event and do the appropriate thread marshalling (if any) for itself.
If you absolutely must get "the main window" then CoreApplication.MainView.CoreWindow will do it.
Related
I have an application in which the worker thread needs to call a method on main thread.
I am planning to send a custom message via win32api.PostThreadMessage(with message WM_USER+X), and when this message is received, some function must get executed on main thread. What I am looking is, to register a method to the corresponding WM_USER_X message?
Look at the RegisterWindowMessage function, it does pretty much exactly what you are after (provides a message number that should not collide with any other). The one downside is that the message number is then not a constant but will vary from run to run of your program, this makes the message loop somewhat more complicated but is well worth it for this sort of thing.
I routinely pass the main form handle to other threads so that they can post messages back to the main thread. I saw that on Sept 28, 2013, Remy Lebeau stated:
...the TWinControl.Handle property is not thread-safe, either. You
should use the TApplication.Handle property instead, or use
AllocateHWnd() to create your own window.
in this answer to a question about passing strings.
How is the handle property not safe? Does it change during the life of the program?
How is the Handle property not safe?
When you access the Handle property, if the window handle has not been created, then it is created on demand. If you access the Handle property from a thread other than the GUI thread, then this means you create the window on the wrong thread.
Does it change during the life of the program?
Yes, the window handle can change if the window is re-created.
I routinely pass the main form handle to other threads so that they can post messages back to the main thread.
In this case, you are probably not accessing the Handle property away from the main thread. It sounds like (although I cannot see your code) you are accessing Handle on the main thread and passing that value to the other thread.
However, window recreation is the problem for you. Since your window is subject to recreation, you simply cannot rely on that handle outliving your thread. Whether or not your window will ever be recreated is hard to predict. The VCL does not perform recreation lightly. However, in my view it is far better to be safe than sorry. So, use AllocateHWnd and take control of the lifetime of this window.
Would someone please answer my question?
Does the C++ program (written using visual studio) create a separate thread for handling mouse events? Would you please describe it concisely?
Thanks
In Windows, each thread that creates a window, and some that don't create any, receive a message queue (and remember that any application has at least one -the main- thread).
This queue is a OS structure that contains any message directed to any windows created by this thread; that includes window handling messages, timers, mouse events directed to any of these windows, keyboard events when any of these windows has the keyboard focus, system events, etc...
It is the responsibility of any thread that has a message queue to pump these messages periodically. This is usually done in what is called the main loop of the thread.
This main loop, in its simplest form is:
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
But it is usually much more convoluted, depending on the complexities of the program.
These two functions:
GetMessage(&msg) removes one message from the queue and puts it in msg. The 0s mean: do not filter.
DispatchMessage(&msg) handles the message, probably calling the callback function relevant to this particular message. With Window messages (mouse and keyboard included) this usually means to locate the window class and then call the window function from within.
So, answering your question: mouse messages are handled in the same thread that created the window that receives them. And it processes them one by one.
No, the mouse events are submitted to the main UI thread/Message loop, along with keyboard and any other peripherals (and system events, and messages from other processes, etc.)
if you want to create a keyboard and mouse hook in Visual C++ 2005 Check this..
http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/3d9bb875-8e79-4c1e-b2ef-b24503e6abbd/how-to-create-a-keyboard-and-mouse-hook-in-visual-c-2005?forum=windowssdk
Actually i am using this code and works ok, but i 'am wondering if is the correct way.
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
The VCL TThread class has its own WaitFor() method that pumps the main message queue internally when called within the main thread context:
MyThread.WaitFor;
ShowMessage('i am done');
Calling Application.ProcessMessages is generally considered a code smell. Let your main thread idle if it's got nothing to do.
If you ran a company and needed one of your workers to run to the store and grab some much-needed supplies, would you then pace by the door until he got back, or would you prefer to sit in your office and rest and wait for him, and find out that the supplies are here because you hear him walk through the door? Either way, he'll take the same amount of time, but the first way's gonna wear your legs out.
Similarly, instead of having your UI watch the thread, have the thread report back to the UI. One way to do this is to have the thread use PostMessage to send a custom message to the form that launched it once it's finished, and put a message handler on the form to respond to it.
It looks correct (if correct means it do the work). What I would change is to wait for a bit more time (50ms looks good to maintain the application responsive) while not eating CPU.
while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
Sure there are other ways to do it... <joke>but I usually apply one of the main engineering principles:
if it works, don't touch it!</joke>
I agree with Mason Wheeler's remark, the main thread is best left to do its job, but I would suggest using the OnTerminate event on the thread. It is more 'Delphi natural' and the internal logic does the PostMessage bit for you. Since TThread is not a component, you can't view it in the object inspector and have to write and attach an event handler yourself. It gets called (in the main thread!) after the thread has completed/terminated.
While it looks okay, like jachguate I would use a bigger time-out value than 0 too. If you use WaitForSingleObject(MyThread.Handle, 100) then the main thread will wait a bit longer, thus eating up less CPU cycles.
A better solution would be the use of messages, though. Your application starts the thread and then puts all controls in disabled mode. The thread then executes and when it's finished, use SendMessage or PostMessage to the main window to notify it that the thread is done again. Then your application will just enable every control (and whatever else) again. This has as advantage that you keep the "natural" messageloop for the application alive, instead of running your own messageloop with this solution.Unfortunately, the message-method has one drawback: if the thread crashes then no message will be sent back, so a backup plan would be practical. For example, by adding a timer control to your mainform which checks every second if the thread is still alive. If not, it too would just activate the form again, disabling itself again.
I have a multi-threaded Delphi 6 Pro application that I am currently working on heavily. If I set a breakpoint on any code that runs in the context of the Main thread (VCL thread) I don't have any problems. However, if a breakpoint is triggered on any code in one of my other threads, after I continue the application from the breakpoint, all repaints to the VCL components on the main thread (including the main form) don't happen anymore. The application isn't dead because other background code keeps running, just the main thread. It's as if the windows message dispatcher has been corrupted or rendered dormant.
Note, in this application I allocate my own WndProc() via allocateHwnd() on the main form because I need to catch certain registered messages. From that WndProc() I dispatch any custom messages I handle and if the current message is not handled by my code, I pass the message on by calling the main form's inherited WndProc(). If I do handle the current message I simply return from my WndProc() with Msg.Result set to 1 to tell the dispatcher that the message was handled. I can't simply override the TForm WndProc() instead of allocating my own WndProc() because for some reason the Delphi VCL does not pass through registered messages instantiated with the Windows API RegisterWindowMessage() call.
Has anybody experienced this in similar context and if so, what did you do to fix it?
-- roscherl
Since you call AllocateHWnd, that means you've created another window. You mustn't just take the messages that were addressed to that window and forward them to your form's window. Doing that, you're bound to screw things up in your program, although I'm not sure exactly how. Painting problems sound plausible. You should make sure it's really just painting problems and not that your main thread is still suspended. The debugger should be able to tell you that. (You should call DefWindowProc to make your allocated window handle messages you're not prepared to handle yourself. And returning 1 doesn't tell the dispatcher anything; the dispatcher doesn't care — whoever called SendMessage wants to know the result.)
I promise you that forms are completely capable of receiving registered window messages. Override WndProc or assign a new value to the WindowProc property (and remember to save the old value so you can call it after handling your own messages). The source of your problem lies elsewhere.
UPDATE: I'm not saying the way I got past the problem is a good solution. I need to take Rob Kennedy's notes and do some refactoring. However, to get past the problem for now I gave the thread it's own Window and WndProc() and at the top of the thread Execute loop I have a PeekMessage() while loop with calls to TranslateMessage() and DispatchMessage(). I no longer have a problem with setting breakpoints in the thread, but obviously this compounding of WndProc() methods indicates a structural problem in my code. I wanted to add this reply to fill out the discussion. I'm hoping that once I put Rob's suggestions to work when I clean up my WndProc() methods on the relevant forms, especially the main form, I can get rid of the this new WndProc() that I just added to the thread.
Robert.