CHAPTER 19 MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING
and Parallel.ForEach() methods both support cancellation through the use of cancellation tokens.
When you invoke methods on Parallel, you can pass in a ParallelOptions object, which in turn
contains a CancellationTokenSource object.
First, define the following new private member variable in your Form derived class of type
CancellationTokenSource named cancelToken:
public partial class MainForm : Form
{
// New Form-level variable.
private CancellationTokenSource cancelToken =
new CancellationTokenSource();
...
}
Now, assuming you have added a new Button (named btnCancel) on your designer, handle the Click
event, and implement the handler as so:
private void btnCancel_Click(object sender, EventArgs e)
{
// This will be used to tell all the worker threads to stop!
cancelToken.Cancel();
}
Now, the real modifications need to occur within the ProcessFiles() method. Consider the final
implementation:
private void ProcessFiles()
{
// Use ParallelOptions instance to store the CancellationToken.
ParallelOptions parOpts = new ParallelOptions();
parOpts.CancellationToken = cancelToken.Token;
parOpts.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
// Load up all *.jpg files, and make a new folder for the modified data.
string[] files = Directory.GetFiles
(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg",
SearchOption.AllDirectories);
string newDir = @"C:\ModifiedPictures";
Directory.CreateDirectory(newDir);
try
{
// Process the image data in a parallel manner!
Parallel.ForEach(files, parOpts, currentFile =>
{
parOpts.CancellationToken.ThrowIfCancellationRequested();
string filename = Path.GetFileName(currentFile);
using (Bitmap bitmap = new Bitmap(currentFile))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
bitmap.Save(Path.Combine(newDir, filename));
737