private void FindThrowOnRemainingCams(CamService succeededCam)
        {
            logger.Info($"Finding throws from remaining cams start. Succeeded cam: {succeededCam.camNumber}");

            foreach (var cam in cams.Where(cam => cam != succeededCam))
            {
                cam.FindThrow();
                cam.FindAndProcessDartContour();
            }

            var thrw = throwService.GetThrow();

            if (thrw != null)
            {
                OnThrowDetected?.Invoke(thrw);
            }

            logger.Info($"Finding throws from remaining cams end");
        }
        public async void RunDetection(List <CamService> camsList,
                                       DetectionServiceWorkingMode mode)
        {
            cams        = camsList;
            workingMode = mode;
            cts         = new CancellationTokenSource();
            cancelToken = cts.Token;

            var extractionSleepTime   = configService.ExtractionSleepTimeValue;
            var thresholdSleepTime    = configService.ThresholdSleepTimeValue;
            var moveDetectedSleepTime = configService.MovesDetectedSleepTimeValue;

            detectionEnabled = configService.DetectionEnabled && !App.NoCams;

            try
            {
                await Task.Run(async() =>
                {
                    OnStatusChanged?.Invoke(DetectionServiceStatus.WaitingThrow);

                    cams.ForEach(c =>
                    {
                        c.DoDetectionCaptures();
                        c.PreviousRoiFrameUpdateFromRoiFrame();
                        c.ThrowExtractedRoiFrameUpdateBlackBlank();
                    });

                    while (!cancelToken.IsCancellationRequested)
                    {
                        foreach (var cam in cams)
                        {
                            cam.DoDetectionCaptures();
                            cam.ThrowExtractedRoiFrameExtractFromRoiPreviousFrame();

                            var result = DetectMoves(cam);

                            if (result == MovesDetectionResult.Nothing)
                            {
                                await Task.Delay(TimeSpan.FromSeconds(thresholdSleepTime));
                                continue;
                            }

                            if (result == MovesDetectionResult.Extraction)
                            {
                                OnStatusChanged?.Invoke(DetectionServiceStatus.DartsExtraction);

                                await Task.Delay(TimeSpan.FromSeconds(extractionSleepTime));

                                foreach (var camToRefresh in cams)
                                {
                                    camToRefresh.DoDetectionCaptures();
                                    camToRefresh.RoiFrameUpdateBlackBlank();
                                    camToRefresh.PreviousRoiFrameUpdateBlackBlank();
                                    camToRefresh.ThrowExtractedRoiFrameUpdateBlackBlank();
                                    Application.Current.Dispatcher.InvokeAsync(() =>
                                    {
                                        camsDetectionBoard.SetCamImages(camToRefresh.camNumber,
                                                                        camToRefresh.GetImage(),
                                                                        camToRefresh.GetRoiImage(),
                                                                        camToRefresh.GetThrowExtractedRoiFrameImage());
                                    });
                                }

                                Application.Current.Dispatcher.InvokeAsync(() =>
                                {
                                    camsDetectionBoard.ClearProjectionImage();
                                    camsDetectionBoard.ClearPointsBox();
                                });

                                OnStatusChanged?.Invoke(DetectionServiceStatus.WaitingThrow);
                                continue;
                            }

                            if (result == MovesDetectionResult.Throw)
                            {
                                OnStatusChanged?.Invoke(DetectionServiceStatus.ProcessingThrow);

                                await Task.Delay(TimeSpan.FromSeconds(moveDetectedSleepTime));

                                foreach (var camWithThrow in cams)
                                {
                                    camWithThrow.DoDetectionCaptures();
                                    camWithThrow.ThrowExtractedRoiFrameExtractFromRoiPreviousFrame();
                                    FindAndProcessDartContour(camWithThrow);
                                    camWithThrow.PreviousRoiFrameUpdateFromRoiFrame();
                                    Application.Current.Dispatcher.InvokeAsync(() =>
                                    {
                                        camsDetectionBoard.SetCamImages(camWithThrow.camNumber,
                                                                        camWithThrow.GetImage(),
                                                                        camWithThrow.GetRoiImage(),
                                                                        camWithThrow.GetThrowExtractedRoiFrameImage());
                                    });
                                }

                                var thrw = throwService.GetThrow();
                                InvokeOnThrowDetected(thrw);
                                OnStatusChanged?.Invoke(DetectionServiceStatus.WaitingThrow);
                            }
                        }
                    }
                });
            }
            catch (Exception e)
            {
                OnErrorOccurred?.Invoke(e);
            }
            finally
            {
                cts?.Cancel();
                throwService.ClearRays();
                cams.ForEach(c => { c.Dispose(); });
            }
        }