private void ProcessPanelQueue() { this.logger.Verbose("In ProcessPanelQueue..."); this.LogInfo(); // sanity check: it's possible that the timer has been paused. we will short circuit here. if (!this.timer.IsEnabled) { this.logger.Info("Timer is paused, exiting ProcessPanelQueue"); return; } // pickup and new panels and add them to the queue. // only add panels not already in the queue this.PanelsDue().ForEach(p => this.panelCaptureQueue.Enqueue(p)); if (!this.panelCaptureQueue.Any()) { this.logger.Verbose("ProcessPanelQueue - No panels to process."); return; } if (this.currentCapture != null) { this.logger.Warn("Cannot Process more queue items, currently waiting on {0}", this.currentCapture.Config.PrettyName); return; } this.logger.Info("Processing {0} panels", this.panelCaptureQueue.Count()); // take the first item and begin processing that, we will chain the processing // when this panel completes or fails we will receive notification and will move // on to the next panel. // NOTE: why we chain - we need to serialize these due to the way we take the screen-shot. // currently I don't have a way to ask the WebView to capture itself, I need // to actually capture the screen. This has it's drawbacks as any other app windows // overlay-ed on top of our WebView will be captured. if (this.panelCaptureQueue.TryDequeue(out ScreenCapturePanel nextPanel)) { this.logger.Info("Dequeued {0}", nextPanel.Config.PrettyName); // we use the current capture as a sanity check to ensure we don't process this again // in addition to checking if the panel itself thinks it is capturing. this.currentCapture = nextPanel; // panels will call back to this ProcessPanelQueue when they are done processing work. // this will allow the queue to continue to drain. // this is an async operation... nextPanel.CaptureScreen(this); } this.LogInfo(); this.logger.Info("Exiting ProcessPanelQueue."); }
public void NotifyPanelProcessingComplete(ScreenCapturePanel panel) { this.logger.Info("Receiving completion notification from panel: {0}", panel.Config.PrettyName); if (this.currentCapture == panel) { this.currentCapture = null; } this.NotifyPanelProcessingCompleteHandler?.Invoke(); this.ProcessPanelQueue(); }
public void SetPanels(ScreenCapturePanel[] panels) { this.panelsToCapture = panels; // it's possible that old panels were in the queue but were removed during a recycle, we'll // add the new versions back into the queue. the ControllerService can be a caller to SetPanels which // is how we would get in this state where the queue had old panels in it. var queueSnapshot = this.panelCaptureQueue.ToList(); this.panelCaptureQueue.Clear(); // compute the min interval var minimumInterval = this.panelsToCapture .Select(panel => panel.Config.Interval) .DefaultIfEmpty(TimeSpan.Zero) .Min(); this.timer.Interval = minimumInterval; if (minimumInterval == TimeSpan.Zero) { this.logger.Warn("TimedCaptureService: timer interval set to Zero, stopping timer"); this.timer.Stop(); } if (queueSnapshot.Any()) { this.logger.Warn("There were items in the queue while SetPanels was being called. Will enqueue new panels for these items"); queueSnapshot.ForEach(oldPanel => { // probably not the most accurate way to do this, we could also just check the config pointer. // the assumption here is that the new panel list will always have a match for an old queued item // if we do not find a match then that queued item will not get run as we have already cleared it from // the queue. var match = this.panelsToCapture.FirstOrDefault(p => p.Config.Name == oldPanel.Config.Name); if (match != null) { logger.Info($"Enqueuing new panel replacement for existing queue item: '{oldPanel.Config.PrettyName}'"); this.panelCaptureQueue.Enqueue(match); } else { this.logger.Warn($"Cannot find new panel for old panel in queue with name '{oldPanel.Config.PrettyName}, old queued item has been dropped'"); } }); } // there could be something processing and now that panel has gone away. lets just clear the current processing // panel prop if (this.currentCapture != null && this.panelsToCapture.FirstOrDefault(p => p == this.currentCapture) == null) { // it's possible with the recycle panels caller we could get into this state. // if the user is adding a new panel then we shuldn't get here. this.logger.Warn("clearing currentCapture, there is no matching panel after set panels"); this.currentCapture = null; } this.LogInfo(); }