public TileGroupEmergingWorker(TileGroup group, ITileQueue emergingQueue, ITileQueue existingQueue = null)
            : base(group, emergingQueue, false)
        {
            _existingQueue = existingQueue ?? emergingQueue;

            _debounceTimer = new System.Timers.Timer(DebounceEvalIntervalSeconds);
            _debounceTimer.Elapsed += (s, e) => ProcessDebounceQueue();
            _debounceQueue = new Dictionary<string, EmergingTileContents>();

            _watcher = new FileSystemWatcher(Group.FullPath, "*.*");
            _watcher.IncludeSubdirectories = true;
            _watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastWrite | NotifyFilters.Size;
            _watcher.Created += (s, e) =>
            {
                // Trace.TraceInformation("-----", e.FullPath);
                // Trace.TraceInformation("File/directory create event for {0}.", e.FullPath);
                try
                {
                    Task.Run(async () =>
                    {
                        await Task.Delay(50);
                        DebounceEnqueue(e.FullPath);
                    });
                }
                catch (Exception ex)
                {
                    Trace.TraceError("An exception occurred debouncing after a Create event: {0}", ex.Message);

                    if (ex.InnerException != null)
                    {
                        Trace.TraceError("Inner exception: {0}", ex.InnerException.Message);
                    }
                }
            };
            _watcher.Changed += (s, e) =>
            {
                // Trace.TraceInformation("-----", e.FullPath);
                // Trace.TraceInformation("File/directory change event ({0}) for {1}.", e.ChangeType, e.FullPath);
                try
                {
                    Task.Run(async () =>
                    {
                        await Task.Delay(50);
                        DebounceEnqueue(e.FullPath);
                    });
                }
                catch (Exception ex)
                {
                    Trace.TraceError("An exception occurred debouncing after a Changed event: {0}", ex.Message);

                    if (ex.InnerException != null)
                    {
                        Trace.TraceError("Inner exception: {0}", ex.InnerException.Message);
                    }
                }
            };
        }
 public TileGroupDiscoverWorker(TileGroup group, ITileQueue queue, bool isExisting = false)
 {
     Group = group;
     IsExisting = isExisting;
     StartTime = DateTime.MinValue;
     Queue = queue;
     DiscoveredCount = 0;
     IsComplete = false;
 }
 public TileEvaluateWorker(ITileQueue sourceQueue = null, ITileQueue incompleteQueue = null, bool isEmerging = true)
 {
     StartTime = DateTime.MinValue;
     Queue = sourceQueue ?? new TileQueue();
     _ownsSourceQueue = sourceQueue == null;
     IncompleteQueue = incompleteQueue ?? new TileQueue();
     _ownsIncompleteQueue = incompleteQueue == null;
     IsEmerging = isEmerging;
     ImplicitChannelFileSize = 0.0;
     ImplicitChannelFrameCount = Int32.MinValue;
 }
 public TileGroupExistingWorker(TileGroup group, ITileQueue queue)
     : base(group, queue, true)
 {
 }
        /// <summary>
        /// Encapsulates the task of observing a root directory for tile additions and changes.
        /// </summary>
        /// <param name="monitor"></param>
        public AcquisitionWorker(AcquisitionMonitor monitor)
        {
            Contract.Requires(monitor != null);

            _model = monitor;
            _hasStarted = false;

            _deserializeCompleteCount = 0;

            _cts = new CancellationTokenSource();

            // Timers (not started)
            _topLevelMonitoringTimer = new System.Timers.Timer(UserOptions.Default.TopLevelDirectoryPollingIntervalMinutes * 60 * 1000);
            _topLevelMonitoringTimer.Elapsed += TopLevelMonitoringElapsed;

            _incompleteMonitoringTimer = new System.Timers.Timer(UserOptions.Default.IncompleteTilePollingIntervalMinutes * 60 * 1000);
            _incompleteMonitoringTimer.Elapsed += EvaluateIncompleteList;

            // Queues
            _incompleteMonitoringQueue = new TileQueue();
            _existingTileQueue = new TileQueue();

            // Discovery workers (not started)
            _discoveryWorkers = new ConcurrentDictionary<TileGroup, TileGroupEmergingWorker>();
            _existingOnlyWorkers = new ConcurrentDictionary<TileGroup, TileGroupExistingWorker>();

            // Evaluate workers (not started)
            _emergingProcessingWorker = new TileEvaluateWorker(null, _incompleteMonitoringQueue, true);

            _existingProcessingWorkers = new List<TileEvaluateWorker>();
            for (int idx = 0; idx < _existingProcessorCount; idx++)
            {
                _existingProcessingWorkers.Add(new TileEvaluateWorker(_existingTileQueue, _incompleteMonitoringQueue, false));
            }

            _incompleteProcessingWorker = new TileEvaluateWorker(null, _incompleteMonitoringQueue, false);

            _duplicateTileWorker = new DuplicateTileWorker();

            // Metadata storage.
            if (UserOptions.Default.SerializeMetadata)
            {
                _metadataCache = new MetadataCache();
            }
            else
            {
                Trace.TraceInformation("Metadata cache has been disabled.  Changes will not be recorded.");
            }
        }