I've started to look at using Omnithread to improve my Delphi Application using multithreading. Creating one or more worker tasks are well covered by the documentation so that long actions that I invoke from button clicks can be replaced by this demo code (Async, CreateTask etc). Where I am having difficulty though is in how to replace my most 'messy' code which operates as follows.
I have a concept of a single class instance that corresponds to a hardware module. The class publishes one or more properties that expose current values and settings for the hardware. Properties might be read only or read / write. For each of these class instances there can be from zero to several display forms visible. A display form has a TTimer and a built list of the aformentioned published properties. This list is iterated to match up suitably named controls such as labels or edit controls and an RTTI mechanism is used to get and set values between the control and its property. The result is a form which provides a nice UI on to the actual hardware module with the side effect than multiple forms can be open, modifying data on one of them causes the others to show that data shortly after. This property monitoring is performed by the TTimer ticking at 300 ms intervals. Each tick causes it to scan through all properties of the class and to refresh the matching control on its form. The timer runs for the lifetime of the open form. Forms are created when needed and then freed (this has the useful performance optimisation that with no forms open to inspect the hardware, the Application must run as fast as possible because no monitoring tasks can be running).
Is there a better way of using threading to access my published properties, rather than using a TTimer in the UI thread? Or would synchronisation issues outweigh any advantages? If threading is useful, how would one create a repeating task such as to emulate the ticking timer?
Related
I've been trying to access cluster variables. Recently I learned that you cant do so using .NET Network Shared Variables and I found that people usually do this via AcitveX.
Using ActiveX I am able to run any VI I want and change the values but most of the VIs that I am trying to access have UI Loops and Consumer Loops. Changing the value of a control manually, fires an event that is detected and leads to certain actions that I am interested in. After reading some old KBs I found out that with ActiveX one can't do that.
Is it the same in LabView 2015? In some forums people discussed creating a VI within the ActiveX program that fires the user events, a sort of a layer. Can someone share examples of such VIs? Are there any other work arounds?
You can programmatic fire a signal event by using the property node -> value(Signaling)
Right click on the control in the block diagram, this can be found under: Create -> Property Node -> Value(Signaling).
Any value written to this node will generate a signal event for this specific control. You don't specifically need ActiveX to generate these events.
You can fire events with property nodes (as already explained by #D.J. Klomp)
You can capture and handle change events with event structures
This can be done even for single controls inside a cluster.
In my program, the creation of the main form is slow : I have identified that it hangs for around two seconds just before the form's OnCreate event is called. So I suspect this is happening while the components are created.
Since this form has several frames, I wonder if there is a way to "profile" component creation in order to see where I can improve. I suspect the lag comes from the opening of a database table that should not be open at that time (rather later, after some filtering is in place).
If there is a way get an event triggered before/after each component creation, I could do the profiling myself (with codesite for example).
Or maybe it is possible to do the component creation manually ?
Here is a quick and dirty way to work out where the delay is:
Take a copy of the Classes unit source code and place it in your project's source folder. This will ensure that this unit is compiled into your program rather than the one supplied with Delphi.
Modify the code in the constructor of TComponent. All streamed components pass through here during creation. Add code to log the class name, e.g. using CodeSite for instance.
Run your program, and then inspect the resulting log to identify the delay.
If you have many components then just knowing the class might not narrow it down. You might inject logging code into TComponent.SetName instead which will let you log the component's name. However, the basic idea is simple enough, and you should be able to apply it to your setting in order to find out the information you need.
I have a large Delphi Application which has core 'server' code containing my data. Within the same app, 'client' the user is able to open and close multiple non-modal 'client' forms to inspect this data. Data changes fall into two types - major (e.g structural changes like data has been added or deleted) and minor such as a change to a data value. Existing open client forms must update to show changed data within a short-ish time. This is not a database, my 'server' using my own data structures so my solutions may have missed possibly standard techniques that are available within a formal database structure. That said, I have repeated my solutions so many times now that I thought I would ask if there are formal techniques and possibly Delphi components that would improve or simplify my code. I am about to move to multithreaded code which make the question even more relevant to me.
I use two methods:
Timestamp. The 'server' code maintains an Int64 value taken from QueryPerformanceCounter. Client forms examine this value on a 300ms ticking timer and update themselves if their copy of the timestamp differs from the server's. I guess this is my 'pull' solution.
Interface notification. The 'server' code maintains a class descended from TInterfaceList with AddClient and RemoveClient methods which register a simple common client notifcation interface. Each of the clients registers itself with this list when created and unregisters on destroy. Data changes at the server trigger an iteration through this list calling each client to advise it of change. I guess this is my 'push' solution.
I love interfaces and solution 2 seems nice since it avoides ticking timers and is easily debugged (although the unregister calls can be problematic with order of destruction). There are potential performance implications tooh because it is quite likely that there may be thousands of data changes per second and I have to be careful to use a BeginUpdate / EndUpdate mechanism to convert my many server data changes into one actual notification call. Ultimately I end up needing a timer of some kind to aggregate the calls into one gentle update of a displayed form.
Both solutions work nicely though and I'm torn between the two. For a mulithreaded solution I'm sure there are other pitfalls I know nothing about. Any comments would be appreciated. I'm using XE2.
You need to take into consideration what you want to happen when the number of clients grows, then decide between the two evils:
is it OK if my performance degrades while being sure all data is current, always and everywhere in the application (then you need the observer pattern)
is it OK if the data in some places lags behind in order to improve performance (then you could use polling and make the interval longer when the poll iterations cause too much slowdown)
I'm not a fan of polling, as it usually leads to very convoluted solutions (well, at least the things I tried, maybe I did it the wrong way back then).
I'd implement the Observer Pattern in Delphi using interfaces, you could use this or this as a start.
A used the Windows API to solve a problem similar to this one. But I believe my approach is simpler. In my applicaion I event didn't know the number of "clients" and which forms where actually clients.
What I did is:
Broadcast a Windows message to all forms opened by my application
(screen.forms[X]). The message includes in the WParam a pointer
to a record which contains information about an event. Also,
different actions broadcast distinc messages. WM_RECORDUPDATE
for DB updates for example.
Windows (clients) listen for message in the way of:
procedure RecordUpdateMessage(var msg: TMessage); message WM_RECORDUPDATE;
Procedure RecordUpdateMessage read the record pointed by msg.WParam and based on the data in the record desides if to react to the update, insert or delete of a record in the DB.
I want to detect when a file date changes and update a DevX TdxMemData which is used as a Tdatasource which then would be seen in a TDBGrid that uses it.
I've found some code that uses ReadDirectoryChangesW, but seems rather complex for my simple needs.
I'm considering using a TTimer and firing it off every five seconds. (That's fine enough accuracy for me.)
Are there any caveats in doing this? I've read that Threads have all sorts of restrictions on VCL access, etc. Does the same thing apply to TTimer events?
Is there anything I need to watch out for when calling FileAge and updating a DevEx TdxMemData object while in a Timer event? Will those updates be seen by my main app?
Is there a way to detect the "state" of my program when a Timer event gets control so I can avoid problems?
Or am I opening an enormous can of worms in thinking about using a TTimer for this?
TTimer events are called within the main application thread, so there's no problems with accessing VCL objects from them. It's called when your application is idle, so it won't take place while your in an OnClick handler or anything similar unless you manually call Application.ProcessMessages.
I'd suggest using ReadDirectoryChangesW though. If you use a timer you will continue polling even if the application is idle and the file isn't changing. It will keep your CPU from going idle and keep could keep the hard drive from spinning down, which can have negative effects for power saving and battery usage.
In Demos directory there's "ShellChangeNotifier" component, which will fire events when files get modified, added or deleted inside directory. However it has only one OnChange event, so you don't know what really happened.
There's some discussion and solution about the issue in about.com
Windows lets you monitor file changes. As a jump start see http://delphi.about.com/od/kbwinshell/l/aa030403a.htm. There are several ready made components available, too. Google for "delphi monitor file change" or something similar
You can check my: DirectoryWatch
It is a wrapper around "ReadDirectoryChangesW" functions. It is more specific about changes than "ShellChangeNotifier".
I'm developing a application in Lazarus, that need to check if there is a new version of a XML file on every Form_Create.
How can I do this?
I have used the synapse library in the past to do this kind of processing. Basically include httpsend in your uses clause, and then call httpgetbinary(url,xmlstream) to retrieve a stream containing the resource. I wouldn't do this in the OnCreate though, since it can take some time to pull the resource. Your better served by placing this in another thread that can make a synchronize call back to the form to enable updates, or set an application flag. This is similar to how the Chrome browser displays updates on the about page, a thread is launched when the form is displayed to check to see if there are updates, and when the thread completes it updates the GUI...this allows other tasks to occur (such as a small animation, or the ability for the user to close the dialog).
Synapse is not a visual component library, it is a library of blocking functions that wrap around most of the common internet protocols.
You'll need to read up on FPC Networking, lNet looks especially useful for this task.