Delphi 7 and events

I'm looking into an error that looks like some kind of synchronization problem and so I'm a little curious about how events work in Delphi 7. What happens is we get some data sent to our application via COM interface and this is handled in an event raised from COM thread. It looks like an event that has quite a lot of code in it takes longer and longer to execute and after a while the whole application crashes. There are calls for the schedule and the addition of large arrays inside the event that can affect timing. I was unable to detect a significant increase in memory usage and was unable to run any profilers to check for leaks. Also, the obvious thing to check is to split the event of all the code on it to see ifwhether it is possible to work for a longer period of time.

Are the events sequential or parallel in Delphi, that is, if I receive a new event at runtime - what happens? Is it running in parallel with some kind of automatic thread, ignored or queued?

If it's queued, how many can I have in the queue before the app crashes?

Does indexing into a large array take longer than further? Even if it's a fixed size? I don't think this is the case, so I am looking for leaks and allocations that take time. If I dispatched an object via an event, should I delete it during the event or in the "calling" code?

What things don't usually scale well in Delphi? What can I look for that will increase at runtime?

Finally, since this is COM related, any pointers to common traps in COM are evaluated, although I understand this is difficult. However, I have a knack for co-initialization.

+1


source to share


3 answers


Delphi is mainly used for event handling. Unfortunately, it can be said that Delphi can handle other events while you are working on some event. As a result, new events will be executed while your current event is waiting for a new event to complete. In the worst case, your application might look fine as long as it actually stacks events into events within events. Rule 1: Avoid using Application.ProcessMessages unless you really need to.

When using COM objects, things get a little more complicated because a COM object can have its own events, start its own threads, and do all the other kinds of things that you don't have. COM seems to be easy to use in Delphi, but it has many hidden pitfalls for inexperienced developers. (I still have scars after you survived some of them!)



In general, when working with COM objects, I try to decouple COM calls in my threads by creating custom components that will contain the COM object inside of it's own thread and adding a lot of synchronization code so that I can keep the GUI responsive while some lengthy COM task does some processing. But it requires a lot of experience with COM and multithreading. But in general, it is good practice to design your custom wrapper component around any COM component, just to protect the resources your COM class needs.

Delphi's biggest weakness tends to handle strings and handling huge arrays. (Especially arrays containing objects use records instead.) Strings themselves are fast in Delphi, but string functions in Delphi are not very optimized. For example, I once had a string containing some XML data. It had many logical fields that were written as "True" and "False" and had to convert them to "true" and "false". To replace all of these values, a simple replacement string took about 15 seconds. I rewrote it using MSXML to load XML into a DOM document, using XPath to select all logical nodes, loop through those nodes to replace all values ​​with the corresponding texts, and then return the XML in one line.Suddenly, he was able to do the same within two seconds! Huge performance for being slower. Cause? When Delphi is processing strings, it tends to copy the string multiple times during processing. Or it needs to allocate more and more memory to grow the string. It takes time that doesn't go to waste in some other languages ​​like C ++.

+2


source


Did some research and got some pointers, especially on my first question:

Are the events sequential or parallel in Delphi, that is, if I receive a new event at runtime - what happens? Is it running in parallel with some kind of automatic thread, ignored or queued? If it's in the queue, how much can I get in the queue before the application crashes?

Well, obviously the events are as synchronous as everything else, or should I say the serial number. You cannot receive more events while handling it, since this event is essentially a function call.



Some graphical components are handled in the event handler. Since the event is raised on a different thread, this is bad. I either have to do some mechanism for updating the graphics, which lies on the thread that created the graphics, or make the thread switch in the event.

In addition, tests show that this is actually a graphics update that is taking more and more time, so refactoring the graphics processing sounds like a good way to try first.

0


source


The important thing for COM is that the "apartment model" supports your application. The most commonly used in Delphi is the single twisted apartment model , also known as "Apartment threaded", where COM calls are synchronized with your main message queue. With this model, you will only be able to handle one COM call at a time, and COM objects do not support calls from other threads.

However, you can initialize your COM apartment model to be multithreaded , and in doing so, you will need to make sure that the shared resources are properly synchronized - each thread that starts must join the multithreaded apartment by callingCoInitializeEx(nil, COINIT_MULTITHREADED);

Things get interesting when you open up the DCOM interfaces, as the RPC subsystem has a pool of threads to service requests that can directly access all of your COM objects in a multi-threaded apartment, allowing for a high-performance server. If you are using flat threading, you will have to go through a bottleneck in the message queue and a single thread can only send one COM call at a time.

Chris Bensen wrote a nice blog post about this too with some code samples.

0


source







All Articles