static void ProcessData(object obj) { DataWithToken dataWithToken = (DataWithToken)obj; if (dataWithToken.Token.IsCancellationRequested) { Console.WriteLine("Canceled before starting {0}", dataWithToken.Data.Num); return; } for (int i = 0; i < 10000; i++) { if (dataWithToken.Token.IsCancellationRequested) { Console.WriteLine("Cancelling while executing {0}", dataWithToken.Data.Num); return; } // Increase this value to slow down the program. Thread.SpinWait(100000); } Console.WriteLine("Processed {0}", dataWithToken.Data.Num); }
static void EventWithCancel() { //<snippet04> IEnumerable <Data> source = GetData(); CancellationTokenSource cts = new CancellationTokenSource(); //Enable cancellation request from a simple UI thread. Task.Factory.StartNew(() => { if (Console.ReadKey().KeyChar == 'c') { cts.Cancel(); } }); // Event must have a count of at least 1 CountdownEvent e = new CountdownEvent(1); // fork work: foreach (Data element in source) { DataWithToken item = new DataWithToken(element, cts.Token); // Dynamically increment signal count. e.AddCount(); ThreadPool.QueueUserWorkItem(delegate(object state) { ProcessData(state); if (!cts.Token.IsCancellationRequested) { e.Signal(); } }, item); } // Decrement the signal count by the one we added // in the constructor. e.Signal(); // The first element could be run on this thread. // Join with work or catch cancellation. try { e.Wait(cts.Token); } catch (OperationCanceledException oce) { if (oce.CancellationToken == cts.Token) { Console.WriteLine("User canceled."); } else { throw; //We don't know who canceled us! } } finally { e.Dispose(); cts.Dispose(); } //... //</snippet04> } //end method