.net 4.5 - listen to Multiple Cancellation requ...

We have learned before that you can cancel operations, while you may have more than one source of cancellation, maybe it is a time out value, maybe it is an expliclity cancellation request that  you can listen and respond to (like an users' action).
Here, we will instruct on the fact on how to listen to multiple cancellation request. the code is from MSDN, but with my own annotation, hope that can clarify something.
Here is the code.
class Program
    {
        // - Joe 
        //   listen to multiple event simultaneouslyu 
        // reference links to http://msdn.microsoft.com/en-us/library/dd997364.aspx
        static void Main(string[] args)
        {
            WorkerWithTimer worker = new WorkerWithTimer();
            CancellationTokenSource externalCts = new CancellationTokenSource();

            // cancellation token
            //   
            Console.WriteLine("Press 'c' to cancel within 3 seconds after work begins.");
            Console.WriteLine("Or let the task time out by doing nothing.");
            if (Console.ReadKey().KeyChar == 'c')
                externalCts.Cancel();  // cancel per user request 

            // Let the user read the UI message.
            Thread.Sleep(1000);

            //p.DoWork(externalCts.Token);
            Task task = Task.Run(() => worker.DoWork(externalCts.Token), externalCts.Token); // remeber to pass in the Token resource 


            try
            {
                task.Wait(externalCts.Token);
            }
            catch (OperationCanceledException e)
            {
                if (e.CancellationToken == externalCts.Token) // which is the source 
                {
                    Console.WriteLine("Canceled from UI thread throwing OCE.");
                }
            }
            catch (AggregateException ae)  // AggregateException has this inner exceptions property? what is this used for ?
            {
                Console.WriteLine("AggregateException caught:" + ae.InnerException);
                foreach (var inner in ae.InnerExceptions) 
                {
                    Console.WriteLine(inner.Message + inner.Source);
                }
            }

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();

       

        }

        class WorkerWithTimer
        {
            CancellationTokenSource internalTokenSource = new CancellationTokenSource();
            CancellationToken internalToken;
            CancellationToken externalToken;
            Timer timer;

            public WorkerWithTimer()
            {
                internalTokenSource = new CancellationTokenSource();
                internalToken = internalTokenSource.Token;

                // A toy cancellation trigger that times out after 3 seconds 
                // if the user does not press 'c'.
                timer = new Timer(new TimerCallback(CancelAfterTimeout), null, 3000, 3000); // cancel via timer, you have 3000 + 3000 seconds for that .
            }


            public void DoWork(CancellationToken externalToken)
            {
                // Create a new token that combines the internal and external tokens. 
                this.internalToken = internalTokenSource.Token;
                this.externalToken = externalToken;

                using (CancellationTokenSource linkedCts =
                        CancellationTokenSource.CreateLinkedTokenSource(internalToken, externalToken))
                {
                    try
                    {
                        DoWorkInternal(linkedCts.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        if (internalToken.IsCancellationRequested)
                        {
                            Console.WriteLine("Operation timed out.");
                        }
                        else if (externalToken.IsCancellationRequested)
                        {
                            Console.WriteLine("Cancelling per user request.");
                            externalToken.ThrowIfCancellationRequested();
                        }
                    }
                }
            }

            private void DoWorkInternal(CancellationToken token)
            {
                for (int i = 0; i < 1000; i++)
                {
                    if (token.IsCancellationRequested)
                    {
                        // We need to dispose the timer if cancellation 
                        // was requested by the external token.
                        timer.Dispose();

                        // Throw the exception.
                        token.ThrowIfCancellationRequested(); // propagate?
                    }

                    // Simulating work.
                    Thread.SpinWait(7500000);
                    Console.Write("working... ");
                }
            }

            public void CancelAfterTimeout(object state)
            {
                Console.WriteLine("\r\nTimer fired.");
                internalTokenSource.Cancel();
                timer.Dispose();
            }
        }


        public void DoWork(CancellationToken externalToken)
        {
            this.internalToken = internalTokenSource.Token;
            this.externalToken = externalToken;

            using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(internalToken, externalToken))
            {
                try
                {
                    DoWorkInternal(linkedCts.Token); // you will pass the linked Cts in, so that you can listen to multiple TokenSource.
                }
                catch (OperationCanceledException)
                {
                    if (internalToken.IsCancellationRequested)
                    {
                        Console.WriteLine("Operation time out.");
                    }
                    else if (externalToken.IsCancellationRequested)
                    {
                        Console.WriteLine("Cancelling per user request.");
                        externalToken.ThrowIfCancellationRequested();
                    }
                }
            }
        }

        void DoWorkInternal(CancellationToken token)
        {
            // do nothing
            for (int i = 0; i < 1000; i++)
            {
                Thread.SpinWait(1000000);
                Console.WriteLine("DoWorkInternal.. ");
            }
        }

        CancellationTokenSource internalTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(20));
        CancellationToken internalToken;
        CancellationToken externalToken;


    }

你可能感兴趣的:(.net,windows,C#,4.5)