internal static List <ApplicationUninstallerEntry> MergeResults(ICollection <ApplicationUninstallerEntry> baseEntries,
                                                                        ICollection <ApplicationUninstallerEntry> newResults, ListGenerationProgress.ListGenerationCallback progressCallback)
        {
            // Add all of the base results straight away
            var results  = new List <ApplicationUninstallerEntry>(baseEntries);
            var progress = 0;

            foreach (var entry in newResults)
            {
                progressCallback?.Invoke(new ListGenerationProgress(progress++, newResults.Count, null));

                var matchedEntry = baseEntries.Select(x => new { x, score = ApplicationEntryTools.AreEntriesRelated(x, entry) })
                                   .Where(x => x.score >= 1)
                                   .OrderByDescending(x => x.score)
                                   .Select(x => x.x)
                                   .FirstOrDefault();

                if (matchedEntry != null)
                {
                    // Prevent setting incorrect UninstallerType
                    if (matchedEntry.UninstallPossible)
                    {
                        entry.UninstallerKind = UninstallerType.Unknown;
                    }

                    InfoAdder.CopyMissingInformation(matchedEntry, entry);
                    continue;
                }

                // If the entry failed to match to anything, add it to the results
                results.Add(entry);
            }

            return(results);
        }
        private void ProgressCallback(ListGenerationProgress report)
        {
            if (_cancelled)
            {
                throw new OperationCanceledException();
            }

            lock (_thread)
            {
                if (_parentProgress == null)
                {
                    _threadLastReport = report;
                }
                else
                {
                    _parentProgress.Inner = report;
                    _callback.Invoke(_parentProgress);
                }
            }
        }
        public List <ApplicationUninstallerEntry> GetResults(ListGenerationProgress.ListGenerationCallback callback,
                                                             ListGenerationProgress parentProgress)
        {
            if (parentProgress == null)
            {
                throw new ArgumentNullException(nameof(parentProgress));
            }
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }
            Debug.Assert(_thread != null);

            if (_thread.IsAlive)
            {
                lock (_thread)
                {
                    _parentProgress = parentProgress;

                    if (_threadLastReport != null)
                    {
                        _parentProgress.Inner = _threadLastReport;
                        callback.Invoke(_parentProgress);
                    }

                    _callback = callback;
                }

                _thread.Join();
            }

            if (_cancelled)
            {
                throw new OperationCanceledException();
            }

            return(_threadResults ?? new List <ApplicationUninstallerEntry>());
        }