Note that there are some explanatory texts on larger screens.

plurals
  1. POPost message from Thread to GUI best practice?
    primarykey
    data
    text
    <p>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).</p> <p>I am thinking about next possibilities:</p> <ul> <li>use <code>Synchronize</code> from every worker thread: </li> <li>use shared buffer and windows messaging mechanism. Thread will put message in shared buffer (queue) and will notify GUI with windows message. </li> <li>use separate thread which will listen for Synchronization primitives (Events, Semaphores, etc) and use again <code>Synchronize</code>, but only from GUI-dedicated thread only, or Critical Section on GUI to display message. </li> <li><strong>UPDATE:</strong> (Proposed by one workmate) use shared buffer and <code>TTimer</code> 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?)</li> <li>Other?</li> </ul> <p>Dear experts, please explain what is the best practice or what are the advantages and disadvantages of exposed alternatives.</p> <p><strong>UPDATE:</strong><br> As idea:<br> //shared buffer + send message variant<br> <code>LogEvent</code> global function will be called from everywhere (from worker threads too):</p> <pre><code>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; </code></pre> <p>In Main Form, where Events ListView and shared section (<code>fEventList: TTInterfaceList</code> which is already thread-safe) we'll be: </p> <pre><code>procedure TMainForm.AddEvent(aEvt: IEventMsg); begin fEventList.Add(aEvt); PostMessage(Self.Handle, WM_EVENT_ADDED, 0, 0); end; </code></pre> <p>Message handler:</p> <pre><code>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 &gt; 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; </code></pre> <p>Is there something bad? Main Form is allocated ONCE on application startup and Destroyed on application exit.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload