This commit is contained in:
meelstorm
2025-10-02 14:14:11 +02:00
parent 63afb2dcfb
commit 44748f2855
9 changed files with 193 additions and 99 deletions

View File

@@ -27,12 +27,18 @@ public abstract class BaseRecognitionControl: IRecognitionControl
public void SetRecipe(RecipeData recipe)
{
// error if running
if (IsRunning)
lock (_lock)
{
throw new InvalidOperationException("Cannot change recipe while recognition is running.");
// error if running
if (IsRunning)
{
throw new InvalidOperationException("Cannot change recipe while recognition is running.");
}
_currentRecipe = recipe;
}
_currentRecipe = recipe;
}
public bool IsRunning { get; set; }
@@ -44,47 +50,57 @@ public abstract class BaseRecognitionControl: IRecognitionControl
private DateTime _startTime;
object _lock = new object();
public void Start()
{
if (_currentRecipe == null)
lock (_lock)
{
throw new InvalidOperationException("No recipe set.");
if (_currentRecipe == null)
{
throw new InvalidOperationException("No recipe set.");
}
if (IsRunning)
{
throw new InvalidOperationException("Recognition is already running.");
}
_loadingService.StartLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}...");
Initialize(_currentRecipe);
_startTime = DateTime.Now;
IsRunning = true;
_cts = new CancellationTokenSource();
Log.Information($"Warming up");
try
{
var swWarmup = Stopwatch.StartNew();
WarmUp();
swWarmup.Stop();
Log.Information($"Warmup run took {swWarmup.ElapsedMilliseconds} ms");
}
catch (Exception ex)
{
Log.Error(ex, "Error during warmup run");
}
_loopTask = Task.Run(() => Loop(_cts.Token), _cts.Token);
SessionStarted?.Invoke(new SessionStartedEvent
{
RecipeName = _currentRecipe.RecipeName,
SessionStarted = _startTime,
});
_loadingService.StopLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}...");
}
if (IsRunning)
{
throw new InvalidOperationException("Recognition is already running.");
}
_loadingService.StartLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}...");
Initialize(_currentRecipe);
_startTime = DateTime.Now;
IsRunning = true;
_cts = new CancellationTokenSource();
Log.Information($"Warming up");
try
{
var swWarmup = Stopwatch.StartNew();
WarmUp();
swWarmup.Stop();
Log.Information($"Warmup run took {swWarmup.ElapsedMilliseconds} ms");
}
catch (Exception ex)
{
Log.Error(ex, "Error during warmup run");
}
_loopTask = Task.Run(() => Loop(_cts.Token), _cts.Token);
SessionStarted?.Invoke(new SessionStartedEvent
{
RecipeName = _currentRecipe.RecipeName,
SessionStarted = _startTime,
});
_loadingService.StopLoading($"Starting recipe {_currentRecipe.RecipeName} on {_settings.CameraName}...");
}
protected abstract void Initialize(RecipeData currentRecipe);
@@ -95,50 +111,62 @@ public abstract class BaseRecognitionControl: IRecognitionControl
public void Stop()
{
if (!IsRunning)
return;
_loadingService.StartLoading($"Stopping {_settings.CameraName}");
_cts?.Cancel();
try
lock (_lock)
{
_loopTask?.Wait();
}
catch (TaskCanceledException)
{
// Ignore cancellation exceptions
}
catch (AggregateException ex) when (ex.Flatten().InnerExceptions.Any(x=>x is TaskCanceledException))
{
// Ignore cancellation exceptions
}
catch(Exception ex)
{
Log.Error(ex, "Error while stopping recognition loop");
}
finally
{
IsRunning = false;
_cts?.Dispose();
_cts = null;
_loopTask = null;
}
if (!IsRunning)
return;
SessionEnded?.Invoke(new SessionEndedEvent
{
SessionEnded = DateTime.Now
});
_loadingService.StopLoading($"Stopping {_settings.CameraName}");
IsPaused=false; // ensure paused is reset
_loadingService.StartLoading($"Stopping {_settings.CameraName}");
_cts?.Cancel();
try
{
_loopTask?.Wait();
}
catch (TaskCanceledException)
{
// Ignore cancellation exceptions
}
catch (AggregateException ex) when (ex.Flatten().InnerExceptions.Any(x => x is TaskCanceledException))
{
// Ignore cancellation exceptions
}
catch (Exception ex)
{
Log.Error(ex, "Error while stopping recognition loop");
}
finally
{
IsRunning = false;
_cts?.Dispose();
_cts = null;
_loopTask = null;
}
SessionEnded?.Invoke(new SessionEndedEvent
{
SessionEnded = DateTime.Now
});
_loadingService.StopLoading($"Stopping {_settings.CameraName}");
IsPaused = false; // ensure paused is reset
}
}
public void Pause()
{
IsPaused = true;
lock (_lock)
{
IsPaused = true;
}
}
public void Resume()
{
IsPaused = false;
lock (_lock)
{
IsPaused = false;
}
}
int _errorsInSequence = 0;
@@ -161,10 +189,13 @@ public abstract class BaseRecognitionControl: IRecognitionControl
{
return;
}
int sleepTime=0;
if (processed.Value.processingTime.Milliseconds < _settings.MinimumProcessingTime)
{
Thread.Sleep(_settings.MinimumProcessingTime - (int)processed.Value.processingTime.Milliseconds);
sleepTime = _settings.MinimumProcessingTime - (int)processed.Value.processingTime.Milliseconds;
Log.Debug("Sleeping for {sleepTime}",sleepTime);
Thread.Sleep(sleepTime);
}
if (processed.Value.errorNames.Length > 0)
@@ -185,6 +216,8 @@ public abstract class BaseRecognitionControl: IRecognitionControl
SessionStart = _startTime,
RecipeName = _currentRecipe.RecipeName,
AnalysisTime = processed.Value.processingTime - processed.Value.acquisitionTime,
AcquisitionTime = processed.Value.acquisitionTime,
SleepTime = TimeSpan.FromMilliseconds(sleepTime),
ErrorNames = processed.Value.errorNames.ToList(),
HasError = processed.Value.errorNames.Length > 0,
ImageSource = _settings.CameraName,
@@ -195,7 +228,7 @@ public abstract class BaseRecognitionControl: IRecognitionControl
var swProcessed = Stopwatch.StartNew();
ImageProcessed(processingResult);
swProcessed.Stop();
Log.Information($"ImageProcessed event handled in {swProcessed.ElapsedMilliseconds} ms");
Log.Information("ImageProcessed event handled in {processed} ms", swProcessed.ElapsedMilliseconds);
}