using System.Collections.Concurrent; using System.ComponentModel; using IBKRTrader.Core.Logging; namespace IBKRTrader.Core.Workers; /// /// Orchestriert alle registrierten IWorker. /// – Startet/stoppt Worker /// – Stellt BindingList für DataGridView bereit /// – Thread-sicher via ConcurrentDictionary /// public class WorkerEngine { private readonly IEnumerable _workers; private readonly LoggingService _logger; private readonly ConcurrentDictionary _registry = new(); private CancellationTokenSource _cts = new(); /// Live-bindbare Liste für dgv_workerlist. public BindingList WorkerInfos { get; } = []; public WorkerEngine(IEnumerable workers, LoggingService logger) { _workers = workers; _logger = logger; } // ─── Engine-Lifecycle ───────────────────────────────────────────────────── public async Task StartAllAsync() { _cts = new CancellationTokenSource(); foreach (var worker in _workers) { RegisterWorker(worker); if (worker.Info.Active) await worker.StartAsync(_cts.Token); } _logger.Info("Core", $"WorkerEngine gestartet – {_registry.Count} Worker/Services registriert."); } public async Task StopAllAsync() { await _cts.CancelAsync(); var tasks = _registry.Values.Select(w => w.StopAsync()); await Task.WhenAll(tasks); _logger.Info("Core", "WorkerEngine gestoppt."); } // ─── Einzelsteuerung ────────────────────────────────────────────────────── public async Task StartWorkerAsync(string name) { if (!_registry.TryGetValue(name, out var worker)) return; worker.Info.Active = true; await worker.StartAsync(_cts.Token); _logger.Info("Core", $"Worker manuell gestartet: {name}"); } public async Task StopWorkerAsync(string name) { if (!_registry.TryGetValue(name, out var worker)) return; worker.Info.Active = false; await worker.StopAsync(); _logger.Info("Core", $"Worker manuell gestoppt: {name}"); } public async Task TriggerWorkerAsync(string name) { if (!_registry.TryGetValue(name, out var worker)) return; await worker.TriggerAsync(); _logger.Info("Core", $"Worker manuell ausgelöst: {name}"); } // ─── Intern ─────────────────────────────────────────────────────────────── private void RegisterWorker(IWorker worker) { _registry[worker.Name] = worker; // WorkerInfo in BindingList eintragen (UI-Thread, falls nötig) if (WorkerInfos is { } list) { if (SynchronizationContext.Current != null) list.Add(worker.Info); else list.Add(worker.Info); } } }