I have a Delphi7 program which implements a com server. Recently the time for program initialisation to complete has increased somewhat due to some new database queries. What I mean by program initlisation is the time it takes for the program to be able to process the incoming com calls in a meaningful way.
My question is how I can handle incoming com calls when the program is not properly initialised yet. Discarding the information contained in the call is not an option, the call needs to wait for the program to initialise.
Will a simple while loop using a boolean initialisation variable be sufficient?
I ask because I read that com calls are executed in the main VCL thread, which would suggest that a while loop would cause the program to hang (The initialisation takes place in the VCL thread as well).
Mutexes cannot be used to waitfor code executing within the same thread, right?
To put it another way, does a com call interupt execution of the (com server's) VCL thread until it is done or how does this concurrent execution of code within the same thread work?
Thanks for taking the time.
Move your database logic out of the main thread so it is not blocked anymore.
COM server (EXE) waits Applcation.Run before return the control flow to the COM client, so all forms and data modules should be initialized.
However, when a form creates another OLE object (i.e. open Word doc in FormCreate() event handler) this may interrupt waiting and return control to the COM client immediately.
Try to check all initialization code of the forms created before Applcation.Run to localize the problem.
Related
Everywhere is noticed that VCL is not thread-safe and we must synchronize access to it. So it's VCL faults that is not thread-safe.
How VCL itself can be thread-safe?
What, precisely, does "thread-safe" mean to you? What about someone else? Every time I see this brought up, it ends up boiling down to this: "I want VCL to be thread-safe so I don't have to think about threading and synchronization issues. I want to write my code as if it is still single-threaded."
No matter how much work went into making VCL so-called "thread-safe", there will always be situations where you can get into trouble. How would you go about making it thread-safe? I don't say this to be combative, rather I merely want to demonstrate that it is not a simple problem with a simple, "works-in-all-cases" solution. To highlight this, let's look at some potential "solutions."
The simplest and most direct approach I see is each component has some kind of "lock", say a mutex or critical section. Every method on the component grabs the lock on entry and then releases the lock just prior to exit. Let's continue down this path with a thought experiment. Consider how Windows processes messages:
Main thread obtains a message from the message queue and then dispatches it to the appropriate WndProc. This message is then routed to the appropriate TWinControl component. Since the component has a "lock", as the message is routed to the appropriate message handler on the component, the lock is acquired. So far so good.
Now take the proverbial button-click message processing. The OnClick message handler is now called which will most likely be a method on the owning TForm. Since the TForm descendant is also a TWinControl component, the TForm's lock is now acquired while the OnClick handler is processed. Now the button component is locked and the TForm component is also locked.
Continuing on this line of thinking, suppose the OnClick handler now wants add an item to a listbox, listview, or some other visual list or grid component. Now suppose some other thread (not the main UI thread) is already in the midst of accessing this same component. Once a method is called on the list from the UI thread it will attempt to acquire the lock, which it cannot since the other thread is currently holding it. As long as the non-UI thread doesn't hold that lock for very long, the UI thread will only block for a brief period.
So far so good, right? Now suppose, that while the non-UI thread is holding the list control's lock, a notification event is called. Since, it will most likely be a method on the owning TForm, upon entry to the event handler, the code will attempt to acquire the lock for the TForm.
Do you see the problem? Remember the button OnClick handler? It already has the TForm lock in the UI thread! It is now blocked waiting for the lock on the list control, which the non-UI thread owns. This is a classic dead-lock. Thread A holds lock A and attempts to acquire lock B which is held by thread B. Thread B is at the same time attempting to acquire lock A.
Clearly, if every control/component has a lock that is automatically acquired and released for every method isn't a solution. What if we left the locking up to the user? Do you see how that also doesn't solve the problem either? How can you be certain that all the code you have (including any third-party components) properly locks/unlocks the controls/components? How does this keep the above scenario from happening?
What about a single shared lock for the whole of VCL? In this scenario, for each message that is processed, the lock is acquired while the message is processed regardless of what component the message is routed to. Again, how does this solve a similar scenario I described above? What if the user's code added other locks for synchronization with other non-UI threads? Even the simple act of blocking until a non-UI thread terminates can cause a dead lock if it is done while the UI thread holds the VCL lock.
What about non-UI components? Database, serial, network, containers, etc...? How should they be handled?
As excellently explained by the other answers, Windows already does a pretty decent job of properly segregating UI message processing to only the thread on which each HWND is created. In fact, learning precisely how Windows works in this regard will go a long way to understanding how you can write your code to work with Windows and VCL in a manner that avoids most of the pitfalls I highlighted above. The bottom line is writing multi-threaded code is difficult, requires a rather drastic mental shift, and lots of practice. Read as much as you can on multi-threading from as many sources as possible. Learn and understand as many coding examples of "thread-safe" code as you can, in any language.
Hopefully this was informative.
The VCL is not thread safe. It is a wrapper around Win32. Win32 is thread safe but has threading rules that give meaning to that statement. Most specifically a window has affinity to the thread that created it.
The design of the Windows message queue means that it is almost always preferable to have all your GUI windows created by the main thread. The VCL designers decided that it was reasonable only to support that mode of operation. And so all VCL code must be executed from the main thread.
There's nothing that can be done to change this. This is by design. If you wish to execute VCL code, it must be done on the main thread. Use TThread.Synchronize or TThread.Queue to arrange that.
There are a lot of reasons why the VCL (especially UI controls) is not thread safe.
Race conditions on message input, especially in code that directly calls TControl.Perform()/TObject.Dispatch() instead of using PostMessage()/SendMessage(). The former does not perform any synchronizing of the control's message handlers, but the latter does. So it is not safe to perform non-HWND based messages from outside of the main thread.
An HWND has thread affinity. It receives and processes messages only on, and can be destroyed only on, the thread context that creates it. A TWinControl can destroy and recreate its HWND at any time, even multiple times, during its lifetime. The TWinControl.Handle property getter creates a new HWND if none exists yet. So if the control is in the process of recreating its HWND when another thread reads from the Handle property, the control can end up with a new HWND that was created in the wrong thread context, making the control no longer responsive to the main message loop (and can potentially leak a second HWND as well). So it is not safe to read from the TWinControl.Handle property from outside of the main thread.
The VCL has a MakeObjectInstance() function that creates a dynamic proxy to allow a TWndMethod class method to be used as a Win32 WNDPROC window callback procedure. All TWinControl controls, and some utility classes like TTimer, use this function. Internally, it maintains a global linked list of proxies, and that list is not protected from concurrent access across threads. So it is not safe to create/destroy HWND-based VCL controls from outside of the main thread.
I'm sure there are other reasons, but these are the big ones.
Everywhere is noticed that VCL is not thread-safe and we must synchronize access to it. So it's VCL faults that is not thread-safe.
How VCL itself can be thread-safe?
What, precisely, does "thread-safe" mean to you? What about someone else? Every time I see this brought up, it ends up boiling down to this: "I want VCL to be thread-safe so I don't have to think about threading and synchronization issues. I want to write my code as if it is still single-threaded."
No matter how much work went into making VCL so-called "thread-safe", there will always be situations where you can get into trouble. How would you go about making it thread-safe? I don't say this to be combative, rather I merely want to demonstrate that it is not a simple problem with a simple, "works-in-all-cases" solution. To highlight this, let's look at some potential "solutions."
The simplest and most direct approach I see is each component has some kind of "lock", say a mutex or critical section. Every method on the component grabs the lock on entry and then releases the lock just prior to exit. Let's continue down this path with a thought experiment. Consider how Windows processes messages:
Main thread obtains a message from the message queue and then dispatches it to the appropriate WndProc. This message is then routed to the appropriate TWinControl component. Since the component has a "lock", as the message is routed to the appropriate message handler on the component, the lock is acquired. So far so good.
Now take the proverbial button-click message processing. The OnClick message handler is now called which will most likely be a method on the owning TForm. Since the TForm descendant is also a TWinControl component, the TForm's lock is now acquired while the OnClick handler is processed. Now the button component is locked and the TForm component is also locked.
Continuing on this line of thinking, suppose the OnClick handler now wants add an item to a listbox, listview, or some other visual list or grid component. Now suppose some other thread (not the main UI thread) is already in the midst of accessing this same component. Once a method is called on the list from the UI thread it will attempt to acquire the lock, which it cannot since the other thread is currently holding it. As long as the non-UI thread doesn't hold that lock for very long, the UI thread will only block for a brief period.
So far so good, right? Now suppose, that while the non-UI thread is holding the list control's lock, a notification event is called. Since, it will most likely be a method on the owning TForm, upon entry to the event handler, the code will attempt to acquire the lock for the TForm.
Do you see the problem? Remember the button OnClick handler? It already has the TForm lock in the UI thread! It is now blocked waiting for the lock on the list control, which the non-UI thread owns. This is a classic dead-lock. Thread A holds lock A and attempts to acquire lock B which is held by thread B. Thread B is at the same time attempting to acquire lock A.
Clearly, if every control/component has a lock that is automatically acquired and released for every method isn't a solution. What if we left the locking up to the user? Do you see how that also doesn't solve the problem either? How can you be certain that all the code you have (including any third-party components) properly locks/unlocks the controls/components? How does this keep the above scenario from happening?
What about a single shared lock for the whole of VCL? In this scenario, for each message that is processed, the lock is acquired while the message is processed regardless of what component the message is routed to. Again, how does this solve a similar scenario I described above? What if the user's code added other locks for synchronization with other non-UI threads? Even the simple act of blocking until a non-UI thread terminates can cause a dead lock if it is done while the UI thread holds the VCL lock.
What about non-UI components? Database, serial, network, containers, etc...? How should they be handled?
As excellently explained by the other answers, Windows already does a pretty decent job of properly segregating UI message processing to only the thread on which each HWND is created. In fact, learning precisely how Windows works in this regard will go a long way to understanding how you can write your code to work with Windows and VCL in a manner that avoids most of the pitfalls I highlighted above. The bottom line is writing multi-threaded code is difficult, requires a rather drastic mental shift, and lots of practice. Read as much as you can on multi-threading from as many sources as possible. Learn and understand as many coding examples of "thread-safe" code as you can, in any language.
Hopefully this was informative.
The VCL is not thread safe. It is a wrapper around Win32. Win32 is thread safe but has threading rules that give meaning to that statement. Most specifically a window has affinity to the thread that created it.
The design of the Windows message queue means that it is almost always preferable to have all your GUI windows created by the main thread. The VCL designers decided that it was reasonable only to support that mode of operation. And so all VCL code must be executed from the main thread.
There's nothing that can be done to change this. This is by design. If you wish to execute VCL code, it must be done on the main thread. Use TThread.Synchronize or TThread.Queue to arrange that.
There are a lot of reasons why the VCL (especially UI controls) is not thread safe.
Race conditions on message input, especially in code that directly calls TControl.Perform()/TObject.Dispatch() instead of using PostMessage()/SendMessage(). The former does not perform any synchronizing of the control's message handlers, but the latter does. So it is not safe to perform non-HWND based messages from outside of the main thread.
An HWND has thread affinity. It receives and processes messages only on, and can be destroyed only on, the thread context that creates it. A TWinControl can destroy and recreate its HWND at any time, even multiple times, during its lifetime. The TWinControl.Handle property getter creates a new HWND if none exists yet. So if the control is in the process of recreating its HWND when another thread reads from the Handle property, the control can end up with a new HWND that was created in the wrong thread context, making the control no longer responsive to the main message loop (and can potentially leak a second HWND as well). So it is not safe to read from the TWinControl.Handle property from outside of the main thread.
The VCL has a MakeObjectInstance() function that creates a dynamic proxy to allow a TWndMethod class method to be used as a Win32 WNDPROC window callback procedure. All TWinControl controls, and some utility classes like TTimer, use this function. Internally, it maintains a global linked list of proxies, and that list is not protected from concurrent access across threads. So it is not safe to create/destroy HWND-based VCL controls from outside of the main thread.
I'm sure there are other reasons, but these are the big ones.
I'm porting an ancient VB6 program to C#/.Net. I don't know VB6 very well and I'm asking this to understand it better.
The old VB6 program had a main course of program execution, but it also had lots of event handlers either for socket events or for timer events and the handlers for these often manipulated shared resources, e.g., common global variables, whenever they woke up and ran.
Nonetheless the old program seemed to run OK.
Trying to do this same architecture in C# is disastrous because event handlers for the socket or timers are called by the system in different threads from the main application thread and result in frequent exceptions like "The calling thread cannot access this object because a different thread owns it.", not to mention more subtle problems. Most of my work in the conversion is re-architecting the program to make it thread-safe, and eliminating the original program's heavy use of global variables.
My question is Do VB6 event handlers run in separate threads? If so how did VB6 ever get away with this? Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
Apartment-Model Threading in Visual Basic
If you want the gritty details, research apartment threading models in COM. VB6 basically uses COM and it's built-in implicity threading models to treat single threads as message-passing entities. It simplifies thread-safety, but underneath you are sacrificing a lot of overhead by basically treating all method calls as queued service calls.
All of your code basically runs in a container that implements COM service calls. If you've ever worked with something written in VB6 in another language, you can interact with them via COM, usually.
Do VB6 event handlers run in separate threads?
Not really, because there aren't separate threads. Your code runs on a single thread, wrapped in the service-like architecture I described above. Most of what you talk to that is threaded is other COM objects which have their own apartments. So to communicate back and forth, you are basically doing RPC calls when the threads talk to each other: you aren't directly manipulating them.
Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
The "timer" is on a separate thread created for the timer, but when it calls into your code, you are guaranteed not to interrupt any other functions, because the function calls are basically queued one at a time in the thread.
My question is Do VB6 event handlers run in separate threads?
Common answer: No.
Real answer: Yes, if you make nasty Win32 calls to spawn more threads. The odds of doing this correctly are close to zero. I don't think I've ever seen it in real code.
Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
When the timer wakes up, it puts a message in the UI's queue. When the UI goes idle, it processes the message and runs the event on the UI thread.
You can do the same thing in WinForms if you use the right timer.
To Matt Wilko, DoEvents is VB6 implementing a virtual cooperative multithreading thing. What's a thread, something that can be interupted to run other code. When you use DoEvents you interupt the execution of your code, when the CPU does multithreading it preempts your code. The effect is the same. One done by VB6 runtime and one by the CPU.
The effect is the same. YOU NEED TO SYNCHRONISE ACCESS TO GLOBAL OBJECTS and VARIABLES.
Your event Handlers aren't supposed to run too long. Each event is queued and run one at a time.
Also the way to multithread a VB6 thing is to put other things in a COM Exe file with a asynchronous model. The exe calls back when finished.
I need to do a project where the application monitors incoming connections and apply some rules as defined in a xml document. The rules are either filtering (blocking or permitting) connections or redirect traffic on a certain port. In order to do this, I use functions such as accept and recv (from Winsock). All of those functions are used on different threads. I'm wondering, though, how am I supposed to clean up the program before exiting since all those blocking calls are made. Normally I'd either wait until the person exits the console through the X button or waiting for the user to input a certain character in the main thread. The thing is I'm not sure what happens if the application exits while there are still active threads/if memory is still allocated/ if sockets are in use. Are all destructors called? Are h andles and sockets correctly closed? Or do I need to somehow do it myself?
Thanks
In general, I would say no. Do not try to explicitly clean up resources like sockets, fd's, handles, threads unless you are absolutely forced to.
Exact behaviour depends on OS and how you terminate your app.
All the common desktop OS will release resources allocated to a process by the OS when a process terminates. This includes sockets, file descriptors, memory.
On Windows/Linux, if you return from your C/C++ main() without any explicit cleanup, static dtors will get called by the crt code. Dtors for dynamically allocated objects in non-main threads are not run.
Executables written in other languages may behave differently.
If, instead of returning from main(), you call a 'ProcessExit()' API directly, static destructors will not get called because the OS has no concept of dtors - it has no idea, or interest, in what language was used to generate the executable.
In either case, the OS will be called to terminate your process. The OS does this, (simple 'Dummies' version:), by first changing the state of all process threads that are not running so that they never run again. Threads that are running on other cores are then stopped. Then OS resources like fd, sockets are closed, then released, then all process memory is freed, then OS kernel process/thread objects freed, then your process no longer exists.
If you absolutely need some, or all, C++/whatever dtors called when some thread needs to stop the app, you will have to explcitly signal other threads to stop so that dtors can be run. I tend to use a globally-accessible 'CloseRequested' bool that relevant blocking calls check immediately after returning. There remains the issue of persuading the blocking calls to return.
Some blocking calls can be coded up to wait on more than one signal, so allowing the call to return by a simple event/sema/condvar/whatever signal.
Some calls, like recv(), accept(), can be pesuaded to return early by closing the fd/socket they are waiting on.
Some calls can be made to return by 'artificially' satisfying their wait condition - eg. creating a temp file just to make a folder-monitor call return so that the 'CloseRequested' bool can be checked.
If a blocking call is so annoyingly stubborn that it cannot be persuaded to return, you could redesign your app so that whatever the critical resource is that is released in the dtors can be released by another thread - maybe create the thing in another thread and pass it to the thread that blocks in a ctor parameter, something like that.
NOTE WELL: Thread shutdown code bodges, as listed above, are extra code that does not add to the normal functionality of your app. You should restrict explicit thread shutdown to those threads that hold resources that absolutely must be released by explicit user code - DB connections, say. If the OS can release the resource, it should be allowed to do so. The OS is very good at stopping all process threads before releasing resources they are using, user code is not.
Where possible, use blocking calls that take a timeout value, and have your threads loop. That gives you a place to check for a shutdown condition and exit the thread gracefully. Handles will generally be cleaned up by the system when the process exits. It is polite to shut down sockets gracefully, but not absolutely mandatory. The downside of not doing so is it can take a while for the kernel to clean up exclusive resources. For example, if you just kill a thread waiting to accept(), and then your app re-launches, it won't be able to successfully accept() on the same port until the kernel cleans up the old socket.
My VC++ 2005 Dialog based application initializes a COM object in the dialog class and uses it in the worker thread.
I called CoInitialize(NULL) At the start of the application and the at the start of the worker thread. But when a COM method is called the error "The application called an interface that was marshalled for a different thread" follows.
If I use CoInitializeEx(0,COINIT_MULTITHREADED) then I will get the same error message
Please help me in finding the root cause.
Thanks.
You created two single-threaded apartments by calling CoInitialize(NULL). An interface pointer must be marshaled from one apartment to the other before it is usable. Initializing the worker thread as MTA doesn't solve the problem. The original interface pointer was still created in a single-threaded apartment and is thus not thread-safe. In other words, you cannot call the interface methods directly from a thread. Those calls have to be marshaled to the thread that created the interface. Marshaling the interface pointer sets up the plumbing that makes that possible.
The only time you don't have to marshal is when both threads are MTA. That's almost never possible, your main thread must be STA if it creates any windows. And the COM server would actually have to be thread-safe, they very rarely are. They advertise what they need with the ThreadingModel key in the registry. COM will actually create an STA thread if necessary to find a good home for the server.
You must marshal the pointer with CoMarshalInterThreadInterfaceInStream() to avoid the error. That's a fairly unfriendly function, IGlobalInterfaceTable is easier to use. The COM server also has to support it, you typically need a proxy/stub DLL that takes care of the marshaling. You'll get E_NOINTERFACE if it doesn't.
Also beware the overhead, marshaling a call from the worker thread to the main thread is pretty expensive and subject to how responsive your main thread is. In other words, if you wrote the thread to speed up your program or to avoid blocking the user interface then this won't actually work. It is the 'there is no free lunch' principle.
Probably CoMarshalInterface() and CoUnMarshalInterface() are the simplest way to do this.
Look at http://support.microsoft.com/kb/206076. You can download the code example and find different implementations of your requirements in Client.cpp.
I think one of the ways to access COM objects inside another thread would be to use Global Interface Pointers. After initialization,form the GIT pointer to the thread along with dwCookie value. Then inside the thread reinterpret-cast the pointer as a DWORD and pass it to the GI table to get our COM pointer.
Thanks