private static void Run(Config config, ILog log, CancellationTokenSource cancelSource) { var trigger = new TriggerService(log, config.Trigger); var files = new FileService(config.Files); using var mail = new MailService(config.Mail, log); using var camera = new CameraService(config.Camera, cancelSource); using var image = new Mat(); if (!camera.TryRead(image)) { return; } var oldDev = camera.MeanStdDev(image); while (!cancelSource.IsCancellationRequested) { camera.Delay(cancelSource.Token); if (!camera.TryRead(image)) { break; } var newDev = camera.MeanStdDev(image); var diff = oldDev.Diff(newDev); if (trigger.ShouldTrigger(diff)) { var path = files.Write(image); mail.Send(path, cancelSource.Token); } oldDev = newDev; } }