/// <summary>
        /// Walk backwards from TargetNode and set parents' IsPartOfTheSolution.
        /// </summary>
        private void SetSolution(CancellationToken cancellationToken)
        {
            Node        node     = grid.TargetNode;
            List <Node> solution = new List <Node>();

            while (node != grid.StartingNode)
            {
                solution.Add(node);
                node = node.Parent;
            }

            solution.Reverse();
            foreach (var n in solution)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    ClearPath();
                    PathfindingFinished?.Invoke(this, null);
                    return;
                }

                n.IsPartOfTheSolution = true;
                //n = n.Parent;
                Thread.Sleep(VisualizationTime * 2);
            }
        }
        public async Task FindPathAsync(CancellationToken cancellationToken)
        {
            await Task.Factory.StartNew(() =>
            {
                if (grid.Algorithm == null)
                {
                    throw new NullReferenceException("Scenario grid does not have an assigned pathfinding algorithim!");
                }

                while (true)
                {
                    if (OpenNodes.Count == 1 && OpenNodes[0] == grid.StartingNode)
                    {
                        CurrentNode = OpenNodes[0];
                    }
                    else
                    {
                        CurrentNode = GetNodeWithLowestFCost(OpenNodes);
                    }
                    Thread.Sleep(VisualizationTime);
                    OpenNodes.Remove(CurrentNode);
                    ClosedNodes.Add(CurrentNode);
                    Thread.Sleep(VisualizationTime);

                    if (CurrentNode == grid.TargetNode)
                    {
                        SetSolution(cancellationToken);
                        PathfindingFinished?.Invoke(this, null);
                        return;
                    }

                    neighbouringNodes = GetNeighbouringNodes(CurrentNode, allowDiagonals: AllowDiagonalMovement);
                    foreach (Node n in neighbouringNodes)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            ClearPath();
                            PathfindingFinished?.Invoke(this, null);
                            return;
                        }

                        if (!n.IsTraversable || ClosedNodes.Contains(n))
                        {
                            continue;
                        }

                        if (IsNewPathShorter(CurrentNode, n) || !OpenNodes.Contains(n))
                        {
                            n.GCost  = CurrentNode.GCost + GetDistance(CurrentNode, n);
                            n.HCost  = GetDistance(n, grid.TargetNode);
                            n.Parent = CurrentNode;

                            if (!OpenNodes.Contains(n))
                            {
                                OpenNodes.Add(n);
                            }
                        }

                        Thread.Sleep(VisualizationTime / 3);
                    }
                }
            });
        }