Cut CPU use and move heavy work off the UI thread

Redraws:
- Merge bursts of session and bandmap events into one redraw
  (Coalesced). Closed Bandmap and Available windows now unsubscribe.
- Grayline and Voice Keyer no longer subscribe to the session twice.
- Available summary, Score table and Log rows redraw only when their
  contents change. Telnet lines are added in batches.
- Bandmap view reuses its layout, shaped text and brushes. Grayline
  draws the coastlines as one cached shape.

Threads:
- Available, Bandmap colours, Check and Statistics do their judging
  and counting on the thread pool and draw the result on the UI thread.
- ContestLog takes a lock in Judge and in each method that changes the
  log, so a background Judge cannot read the indexes mid-edit.

Refresh rate:
- Statistics refreshes every 30 seconds and when the QSO count changes.
- Grayline refreshes at most every 15 seconds on session events.

Publish with ReadyToRun to cut startup JIT time.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 12:25:46 +00:00
co-authored by Claude Sonnet 5.5
parent 0a23815f38
commit fe70f9b058
19 changed files with 752 additions and 184 deletions
+6 -1
View File
@@ -223,7 +223,12 @@ public sealed partial class LogWindow : RefreshableWindow
bool atBottom = ScrolledToBottom();
for (int at = 0; at < shownRows.Count; at++)
{
shownRows[at].Show(qsos[at], VerdictFor(qsos[at]));
// a contact that was not edited is the same object, and the
// row has nothing to redraw
if (!ReferenceEquals(shownRows[at].Qso, qsos[at]))
{
shownRows[at].Show(qsos[at], VerdictFor(qsos[at]));
}
}
bool grown = qsos.Count > shownRows.Count;
for (int at = shownRows.Count; at < qsos.Count; at++)