I am in support of an application that involves serial port communication.
There are 32 MSComm controls (control array) on the form.
Suppose data arrived at one of the com port while some other code of the same thread is running (say database access etc.). will the Oncomm event procedure queed for execution or the current execution point is queed and Oncomm event handler is executed?
VB6 is single threaded. Basically (excepting ActiveX controls for a second) there's just the GUI thread.
It's sitting there waiting for an event. You get data, so it enters the event handler for your MSComm control and starts doing some database access. It blocks waiting for the database to respond. Another MSComm control receives data and fires off an event. This event just sits in the Windows event queue. The GUI thread has to exit the event handler before it can process the other MSComm event.
Of course, in the middle of an event handler you can call DoEvents. I highly suggest you rarely, if ever, do that. It's the source of many difficult bugs, in my experience.
There are ways to queue the long running database work onto a background thread (using a call into .NET managed code, in that case). That will allow your event handler code to continue almost immediately without blocking, allowing it to process the next message. To my knowledge, there's no native VB6 way to do that.
Related
I have a program that shuts down another application when certain conditions are met. Now most of the time everything works out fine, but sometimes the app is writing to a file and leaves it in a half finished state and has no way of recovering it on restart. I thought that one could send soft close signals and escalate after certain timeouts to more aggressive close signals, going trough a list like this:
1. WM_CLOSE
2. WM_QUIT
3. WM_DESTROY
4. TerminateProcess().
Now I know that the program has no code to handle any signal it receives. Is there a possibility that certain FileHandler under Windows react gracefully on such soft signals or is there no use to sending those, if the app does not handle them explicitly?
This article says:
NOTE: A console application's response to WM_CLOSE depends on whether or not it has installed a control handler.
Does this mean if no control handler is installed sending 1-4 is just as good as sending 4 directly?
I have wrote one sample com server which implements com connection point. I am calling one method in this COM object which in turn calling some other method in my client code using connection point mechanism.
But all the above listed operation is synchronous communication. I would like to make COM server pure async so that if my COM server get some event it should fire the data back to its client.
please suggest how it is possible using COM connection point.
Note :- My COM server is running as a exe out of proc.
Thanks in advance!!!
Regards
Ashish
Threading is never a minor detail in COM, just as it isn't in any runtime environment. You must observe the apartment state that the COM client program selected. And if it is STA, by far the most common selection, then it is your duty to fire the event on the thread that the client code selected. Ignoring that requirement just produces impossible to diagnose bugs in the client program.
So if you fire the event from a worker thread in your own code, the only way to get event handlers to run async, then you must marshal the interface pointer. CoMarshalThreadInterfaceInStream() or the easier-to-use IGlobalInterfaceTable gets that job done. Rock-hard requirement. It will run asynchronously when the client program opted-in by using COINIT_MULTITHREADED when it called CoInitializeEx(). The only thing you can do is publish the fact that your code is thread-safe by picking the ThreadingModel registry value, using "Both" or "Free".
Same as you do it without COM:
the client of your server object calls a method;
the method starts a background operation and returns;
The background operation can use a separate thread, an async I/O API, a timer API, etc. When the background operation has completed, it fires an event (calls a method on the client-provided sink interface);
the client handles the event.
Back to COM, all method invocations in COM are synchronous by default. When you fire an event on the client-provided sink interface, the call will block until the client returns. There's one exception to this behavior: IAdviseSink. The methods of this interface are asynchronous, if the callee resides in a different COM apartment from the caller. However, IAdviseSink is probably not what you're looking for.
The standard way to use asynchronous COM requires that the interface have an separate UUID for the asynchronous interface. IConnectionPoint does not have an async UUID, so you can't use ICallFactory to implement asynchronous COM.
I am using global event listener in my application. The event capture perfectly works in my code. The problem is the event seems to be fire multiple time. I have followed this tutorial link.
If your app is listening to global events generated by system, then these events may fire several times according to conditions you do not know. On my experience to get a univocal signal from the system I had to analyze a sequence of global events and the signal was recognized as received only when this sequence of events occured one after another in expected way.
If your app is listening to global events generated by your application, then it is fully under your control. Check your code that fires global events. Use EventLogger to log every moment when you fire and when you receive fired event. Then inspect your log to find out what is going on. Seems that your app fires the global event more times than expected.
I've got no idea how window hooks work at the "system level". MSDN only touches what's going on very briefly:
A hook is a point in the system message-handling mechanism where an
application can install a subroutine to monitor the message traffic in
the system and process certain types of messages before they reach the
target window procedure.
My best guess is something like below:
Before each message is added to the message queue for a window, it'll first send the message to the global/local hooks, which may do something, depending on their hook procedures. After all global hooks and local hooks, the message is finally added to the window message queue.
However, MSDN says that for some of the types of hooks, it will monitor events, notifications etc.
An example is the WH_MOUSE_LL hook:
Installs a hook procedure that monitors low-level mouse
input events. For more information, see the LowLevelMouseProc hook
procedure.
When they say events, are we talking window messages, or do they mean something else?
Am I all wrong?
Yes, this is a mechanism for windows messages, you can process this data (messages) before they reach target window procedure (message loop).
If you want hook other process windows you can simply do this in DLL, and use DLL injection for inject your library to other process.
I am porting a library to Windows. In a function I need to block on the arrival of a WM_DEVICECHANGE message.
What options are available for doing this? As my code resides in a library I have little-to-no information on the current set-up (so if it is a Console application, a regular GUI application, if my code is being run in a spawned thread, and so on). Therefore what is the best way to wait for the arrival of a specific message?
Blocking and receiving Windows messages are mutually incompatible. You get messages by pumping a message loop. Since you cannot rely on the app pumping one, you'll need to do this yourself.
You will need to create a thread. Create a hidden window in that thread then run the standard message loop. The window procedure for that window can see the WM_DEVICECHANGE message. It can do what ever it needs to do, within the constraints of running inside a separate thread. Like setting an event to signal that a function should stop blocking.
The message is probably sent using BroadcastSystemMessage(). You could create a hidden top-level window and its window proc would probably get this message. I'm not sure; but that's what I'd try first.