/// <summary>
        /// Crawls the graph set as the graphToCrawl in the constructor, starting with the vertex specified. If the vertex isn't in the graph, the routine is a no-op
        /// </summary>
        /// <param name="vertexToStart">The vertex to start the crawl operation.</param>
        /// <remarks>vertexToStart can't be null, as a graph can't contain null vertices</remarks>
        protected void Crawl(TVertex vertexToStart)
        {
            if (((object)vertexToStart == null) || (!_graphToCrawl.Contains(vertexToStart)))
            {
                return;
            }
            var  verticesProcessed            = new Dictionary <TVertex, VertexColor>();
            bool firstRun                     = true;
            IEnumerable <TVertex> toEnumerate = _graphToCrawl.Vertices;

            if (_graphToCrawl.IsSynchronized)
            {
                // create safe copy to work with. This can be a bit of a problem regarding performance with massive graphs, but toArray is in general rather quick.
                toEnumerate = GeneralUtils.PerformSyncedAction(() => _graphToCrawl.Vertices.ToArray(), _graphToCrawl.SyncRoot, _graphToCrawl.IsSynchronized);
            }
            foreach (TVertex vertex in toEnumerate)
            {
                if (_abortCrawl)
                {
                    break;
                }
                TVertex vertexToProcess = vertex;
                if (firstRun)
                {
                    // simply use the vertexToStart. As it's being processed right away, any subsequential occurence later on will be a no-op as the vertex has
                    // already been processed.
                    vertexToProcess = vertexToStart;
                    firstRun        = false;
                }
                if (!verticesProcessed.ContainsKey(vertexToProcess))
                {
                    verticesProcessed.Add(vertexToProcess, VertexColor.NotVisited);
                }
                if (verticesProcessed[vertexToProcess] != VertexColor.NotVisited)
                {
                    continue;
                }
                // we only get back to this level for tree roots if it's a non-directed graph. If it's a directed graph, we can end up here as well if we moved
                // into a path to a vertex which has no out-going edges.
                if (!_graphToCrawl.IsDirected)
                {
                    RootDetected(vertexToProcess);
                }
                Visit(vertexToProcess, verticesProcessed, null);
            }
        }
        /// <summary>
        /// Crawls the graph set as the graphToCrawl in the constructor, starting with the vertex specified. If the vertex isn't in the graph, the routine is a no-op
        /// </summary>
        /// <param name="vertexToStart">The vertex to start the crawl operation.</param>
        /// <remarks>vertexToStart can't be null, as a graph can't contain null vertices</remarks>
        protected void Crawl(TVertex vertexToStart)
        {
            if (((object)vertexToStart == null) || (!_graphToCrawl.Contains(vertexToStart)))
            {
                return;
            }
            var  verticesProcessed = new Dictionary <TVertex, VertexColor>();
            bool firstRun          = true;

            foreach (TVertex vertex in _graphToCrawl.Vertices)
            {
                if (_abortCrawl)
                {
                    break;
                }
                TVertex vertexToProcess = vertex;
                if (firstRun)
                {
                    // simply use the vertexToStart. As it's being processed right away, any subsequential occurence later on will be a no-op as the vertex has
                    // already been processed.
                    vertexToProcess = vertexToStart;
                    firstRun        = false;
                }
                if (!verticesProcessed.ContainsKey(vertexToProcess))
                {
                    verticesProcessed.Add(vertexToProcess, VertexColor.NotVisited);
                }
                if (verticesProcessed[vertexToProcess] != VertexColor.NotVisited)
                {
                    continue;
                }
                // we only get back to this level for tree roots if it's a non-directed graph. If it's a directed graph, we can end up here as well if we moved
                // into a path to a vertex which has no out-going edges.
                if (!_graphToCrawl.IsDirected)
                {
                    RootDetected(vertexToProcess);
                }
                Visit(vertexToProcess, verticesProcessed, null);
            }
        }