Free mag vol1 | Page 793

CHAPTER 19  MULTITHREADED, PARALLEL, AND ASYNC PROGRAMMING } this.Invoke((Action)delegate { this.Text = string.Format("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId); } ); } ); } } catch (OperationCanceledException ex) { this.Invoke((Action)delegate { this.Text = ex.Message; }); } Notice that you begin the method by configuring a ParallelOptions object, setting the CancellationToken property to use the CancellationTokenSource token. Also note that when you call the Parallel.ForEach() method, you pass in the ParallelOptions object as the second parameter. Within the scope of the looping logic, you make a call to ThrowIfCancellationRequested() on the token, which will ensure if the user clicks the Cancel button, all threads will stop and you will be notified via a runtime exception. When you catch the OperationCanceledException error, you will set the text of the main window to the error message.  Source Code The DataParallelismWithForEach project is included under the Chapter 19 subdirectory. Task Parallelism Using the Parallel Class In addition to data parallelism, the TPL can also be used to easily fire off any number of asynchronous tasks using the Parallel.Invoke() method. This approach is a bit more straightforward than using delegates or members from System.Threading; however, if you require more control over the way tasks are executed, you could forgo use of Parallel.Invoke() and make use of the Task class directly, as you did in the previous example. To illustrate task parallelism, create a new Windows Forms application called MyEBookReader and be sure the System.Threading.Tasks and System.Net namespaces are imported. This example is a modification of a useful example in the .NET Framework 4.5 SDK documentation. Here, we will fetch a publically available e-book from Project Gutenberg (www.gutenberg.org), and then perform a set of lengthy tasks in parallel. The GUI consists of a multiline TextBox control (named txtBook) and two Button controls (btnDownload and btnGetStats). Once you have designed the UI, handle the Click event for each Button, and in the form’s code file, declare a class-level string variable named theEBook. Implement the Click hander for the btnDownload as so: 738