.NET WinForms-Anwendung (Core, Modules/CongressTrading, UI). Enthaelt .gitignore und settings.example.json als Konfigurationsvorlage. Echte settings.json mit Zugangsdaten ist bewusst ausgeschlossen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
97 lines
3.3 KiB
C#
97 lines
3.3 KiB
C#
using System.Collections.Concurrent;
|
||
using System.ComponentModel;
|
||
using IBKRTrader.Core.Logging;
|
||
|
||
namespace IBKRTrader.Core.Workers;
|
||
|
||
/// <summary>
|
||
/// Orchestriert alle registrierten IWorker.
|
||
/// – Startet/stoppt Worker
|
||
/// – Stellt BindingList für DataGridView bereit
|
||
/// – Thread-sicher via ConcurrentDictionary
|
||
/// </summary>
|
||
public class WorkerEngine
|
||
{
|
||
private readonly IEnumerable<IWorker> _workers;
|
||
private readonly LoggingService _logger;
|
||
private readonly ConcurrentDictionary<string, IWorker> _registry = new();
|
||
private CancellationTokenSource _cts = new();
|
||
|
||
/// <summary>Live-bindbare Liste für dgv_workerlist.</summary>
|
||
public BindingList<WorkerInfo> WorkerInfos { get; } = [];
|
||
|
||
public WorkerEngine(IEnumerable<IWorker> 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);
|
||
}
|
||
}
|
||
}
|