private static void DoWork()
        {
            Console.WriteLine();
            Console.WriteLine("Url: " + url);
            Console.WriteLine("User Name: " + userName);
            Console.WriteLine("List Name: " + listName);
            Console.WriteLine();
            try
            {
                Console.WriteLine(string.Format("Connecting to {0}", url));
                Console.WriteLine();
                ClientContext cc = new ClientContext(url);
                cc.AuthenticationMode = ClientAuthenticationMode.Default;

                cc.Credentials = new SharePointOnlineCredentials(userName, password);

                ListCollection     lists   = cc.Web.Lists;
                IEnumerable <List> results = cc.LoadQuery <List>(lists.Where(lst => lst.Title == listName));
                cc.ExecuteQuery();
                List list = results.FirstOrDefault();
                if (list == null)
                {
                    Console.WriteLine("A list named \"{0}\" does not exist. Press any key to exit...", listName);
                    Console.ReadKey();
                    return;
                }

                nextRunTime = DateTime.Now;

                ChangeQuery cq = new ChangeQuery(false, false);
                cq.Item         = true;
                cq.DeleteObject = true;
                cq.Add          = true;
                cq.Update       = true;

                // Initially set the ChangeTokenStart to 2 days ago so we don't go off and grab every item from the list since the day it was created.
                // The format of the string is semicolon delimited with the following pieces of information in order
                // Version number
                // A number indicating the change scope: 0 – Content Database, 1 – site collection, 2 – site, 3 – list.
                // GUID representing the scope ID of the change token
                // Time (in UTC) when the change occurred
                // Number of the change relative to other changes
                cq.ChangeTokenStart             = new ChangeToken();
                cq.ChangeTokenStart.StringValue = string.Format("1;3;{0};{1};-1", list.Id.ToString(), DateTime.Now.AddDays(-2).ToUniversalTime().Ticks.ToString());

                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(string.Format("Ctrl+c to terminate. Press \"r\" key to force run without waiting {0} seconds.", WaitSeconds));
                Console.WriteLine();
                Console.ResetColor();
                do
                {
                    do
                    {
                        if (Console.KeyAvailable && Console.ReadKey(true).KeyChar == 'r')
                        {
                            break;
                        }
                    }while (nextRunTime > DateTime.Now);

                    Console.WriteLine(string.Format("Looking for items modified after {0} UTC", GetDateStringFromChangeToken(cq.ChangeTokenStart)));


                    ChangeCollection coll = list.GetChanges(cq);
                    cc.Load(coll);
                    cc.ExecuteQuery();


                    DisplayChanges(coll, cq.ChangeTokenStart);
                    // if we find any changes to the list take the last change and use the ChangeToken as the start time for our next query.
                    // The ChangeToken will contain the Date/time of the last change to any item in the list.
                    cq.ChangeTokenStart = coll.Count > 0 ? coll.Last().ChangeToken : cq.ChangeTokenStart;

                    nextRunTime = DateTime.Now.AddSeconds(WaitSeconds);
                } while (true);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }