Initial commit: IBKRTrader

.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>
This commit is contained in:
Richard
2026-07-26 18:19:47 +02:00
co-authored by Claude Opus 4.8
commit ebeb035e92
47 changed files with 4527 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
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);
}
}
}