Just perform a Fisher-Yates shuffle, however the random you pass in seed with a fixed value instead of allowing it to just be based on system ticks.
public static class ExtensionMethods
{
    public static void Shuffle<T>(this IList<T> list, Random rng)
    {
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = rng.Next(n + 1);
            T value = list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }
}
then in your code do something similar to
public class Program
{
    public static void Main(string[] args)
    {
        var list = new String[] {"Angie", "David", "Emily", "James"};
        var baseSeed = Environment.TickCount;
        for (int i = 0; i < 100; i++)
        {
            Random rnd = new Random(baseSeed + i / 10);
            var shuffled = list.ToList(); //This is so we don't mutate the original list with Shuffle
            shuffled.Shuffle(rnd);
            Console.WriteLine(String.Join(",", shuffled));
            Thread.Sleep(100);
        }
        Console.ReadLine();
    }
}
This would make shuffled have the same result 10 times in a row then it would change to a new order and keep that new order for 10 times in a row. Every time you run the program you will get a different result because it will use a new base Environment.TickCount to start it's offset from. If you just use new Random() it actually just does new Random(Environment.TickCount)