I am working on small monitoring application which will have some threads for communication with some devices via SNMP, TCP, ICMP, other threads have to perform some calculations. All this result I have to output in GUI (some Forms or TabSheets).
I am thinking about next possibilities:
- use
Synchronize
from every worker thread: - use shared buffer and windows messaging mechanism. Thread will put message in shared buffer (queue) and will notify GUI with windows message.
- use separate thread which will listen for Synchronization primitives (Events, Semaphores, etc) and use again
Synchronize
, but only from GUI-dedicated thread only, or Critical Section on GUI to display message. - UPDATE: (Proposed by one workmate) use shared buffer and
TTimer
in main form which will check periodically (100-1000 ms) shared buffer and consuming, instead of windows messaging. (Does it have some benefit over messaging?) - Other?
Dear experts, please explain what is the best practice or what are the advantages and disadvantages of exposed alternatives.
UPDATE:
As idea:
//shared buffer + send message variant
LogEvent
global function will be called from everywhere (from worker threads too):
procedure LogEvent(S: String);
var
liEvent: IEventMsg;
begin
liEvent := TEventMsg.Create; //Interfaced object
with liEvent do
begin
Severity := llDebug;
EventType := 'General';
Source := 'Application';
Description := S;
end;
MainForm.AddEvent(liEvent); //Invoke main form directly
end;
In Main Form, where Events ListView and shared section (fEventList: TTInterfaceList
which is already thread-safe) we'll be:
procedure TMainForm.AddEvent(aEvt: IEventMsg);
begin
fEventList.Add(aEvt);
PostMessage(Self.Handle, WM_EVENT_ADDED, 0, 0);
end;
Message handler:
procedure WMEventAdded(var Message: TMessage); message WM_EVENT_ADDED;
...
procedure TMainForm.WMEventAdded(var Message: TMessage);
var
liEvt: IEventMsg;
ListItem: TListItem;
begin
fEventList.Lock;
try
while fEventList.Count > 0 do
begin
liEvt := IEventMsg(fEventList.First);
fEventList.Delete(0);
with lvEvents do //TListView
begin
ListItem := Items.Add;
ListItem.Caption := SeverityNames[liEvt.Severity];
ListItem.SubItems.Add(DateTimeToStr(now));
ListItem.SubItems.Add(liEvt.EventType);
ListItem.SubItems.Add(liEvt.Source);
ListItem.SubItems.Add(liEvt.Description);
end;
end;
finally
fEventList.UnLock;
end;
end;
Is there something bad? Main Form is allocated ONCE on application startup and Destroyed on application exit.