Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common/BusyIndicatorManager.md
2026-04-17 14:55:32 -04:00

6.5 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.Common/BusyIndicatorManager/xBusyIndicator.xaml.cs
Common/DTS.Common/BusyIndicatorManager/BusyIndicatorManager.cs
2026-04-16T02:51:55.325916+00:00 Qwen/Qwen3-Coder-Next-FP8 1 abbbba42817259f5

BusyIndicatorManager

Documentation: BusyIndicatorManager Module


1. Purpose

This module provides a centralized, singleton-based busy indicator management system for WPF applications using Prism. It coordinates multiple concurrent "busy sessions" (identified by integer IDs) and ensures the UI busy indicator reflects the aggregate state: if any session is active, the indicator is shown with the message from the most recently added or updated active session. It decouples business logic from UI presentation by exposing observable properties (IsBusy, Message) that can be bound to a BusyIndicator control (e.g., Xceed.Wpf.Toolkit.BusyIndicator), while allowing multiple components to request and release busy state independently without interfering with each other.


2. Public Interface

BusyIndicatorManager (Singleton Class)

  • public static BusyIndicatorManager Instance { get; }
    Thread-safe singleton accessor. Returns the single shared instance of BusyIndicatorManager. Uses double-checked locking via SyncRoot.

  • public bool IsBusy { get; }
    Read-only property indicating whether any busy session is currently active. Raises PropertyChanged on change (via BindableBase).
    Note: Set only internally via RaisePropertyChanged.

  • public string Message { get; }
    Read-only property containing the message to display in the busy indicator. Reflects the message of the last added/updated active session (see ShowBusy/CloseBusy logic). Raises PropertyChanged on change.

  • public void ShowBusy(int id, string busyMessage)
    Registers or updates a busy session identified by id.

    • If id is new: adds (id, busyMessage) to busyParameters, sets IsBusy = true, and sets Message = busyMessage.
    • If id already exists: updates its message in busyParameters, sets IsBusy = true, and sets Message = busyMessage (i.e., always updates to the latest message for this session).
  • public void CloseBusy(int id)
    Removes the busy session identified by id.

    • If id exists: removes it from busyParameters.
    • After removal:
      • If busyParameters.Count == 0: sets IsBusy = false, Message = string.Empty.
      • Else: sets IsBusy = true, Message = busyParameters.Last().Value (i.e., message from the last-enumerated remaining session — not necessarily the most recent).

xBusyIndicator (Partial Class)

  • public xBusyIndicator()
    Constructor. Calls InitializeComponent() to load XAML resources.

  • public void Connect(int connectionId, object target)
    Currently empty implementation. No behavior defined in source. Purpose unclear without additional context.


3. Invariants

  • Session uniqueness: Each id passed to ShowBusy/CloseBusy must be unique per caller to avoid unintended overwrites or conflicts. The manager does not enforce uniqueness across callers.
  • Message semantics: Message always reflects the value of the last entry in the busyParameters dictionary (via Last()), which depends on dictionary enumeration order (insertion order in .NET 6+ for Dictionary<TKey, TValue>). This is not guaranteed to be the most recently added session if sessions are closed/reopened.
  • State consistency: IsBusy is true iff busyParameters.Count > 0.
  • Thread safety: Singleton instantiation is thread-safe via lock(SyncRoot). However, all other methods (ShowBusy, CloseBusy) are not thread-safe — concurrent calls may corrupt busyParameters (e.g., race in ContainsKey/Add/Remove).
  • No cleanup on ID reuse: Reusing an id after CloseBusy(id) will overwrite the previous sessions message (via ShowBusy), but no explicit cleanup of stale references occurs beyond the dictionary update.

4. Dependencies

Dependencies of this module:

  • Prism.Mvvm: Used via BindableBase for property change notification (RaisePropertyChanged).
  • System.Collections.Generic: For Dictionary<int, string>.
  • System.Linq: For Dictionary.Last() in CloseBusy.
  • Xceed.Wpf.Toolkit: Referenced via BusyIndicator usage (implied by xBusyIndicator.xaml), though not directly used in the C# code shown.
  • WPF: System.Windows.Controls (likely for BusyIndicator control usage in XAML).

Dependencies on this module:

  • Any UI component needing to show/hide a busy indicator must reference DTS.Common.BusyIndicatorManager and use BusyIndicatorManager.Instance.ShowBusy(...) / CloseBusy(...).
  • xBusyIndicator.xaml (WPF user control) likely binds to BusyIndicatorManager.Instance.IsBusy and Message (though binding logic is not in the provided source).
  • Inferred usage pattern: Components call ShowBusy(id, msg) before long-running operations and CloseBusy(id) afterward (e.g., in try/finally blocks).

5. Gotchas

  • Non-deterministic message on partial close: In CloseBusy, Message is set to busyParameters.Last().Value. Since Dictionary<TKey, TValue> enumeration order is insertion order (in modern .NET), this uses the oldest remaining sessions message — not the most recently added one. This may cause confusing UI behavior if sessions overlap.
  • No ID validation: ShowBusy and CloseBusy accept any int id. Negative or zero IDs are allowed but may cause conflicts if callers reuse IDs carelessly.
  • Thread-unsafety: Methods ShowBusy and CloseBusy lack synchronization. Concurrent calls (e.g., from background threads) may cause InvalidOperationException (e.g., modifying collection during enumeration) or inconsistent state.
  • Empty Connect method: The xBusyIndicator.Connect method has no implementation. Its purpose is unclear — possibly a placeholder for future binding logic or event wiring.
  • No timeout/cleanup mechanism: Idle busy sessions (e.g., due to exceptions skipping CloseBusy) persist indefinitely until manually closed.
  • Message overwrites: Calling ShowBusy(id, msg) for an existing id overwrites the message but does not reset the sessions position in the dictionary (so Last() may still refer to an older session).

None identified from source alone.
Correction: Several gotchas are apparent (see above).