Lập trình .net 4.0 và visual studio 2010 part 16 doc

6 350 0
Lập trình .net 4.0 và visual studio 2010 part 16 doc

Đang tải... (xem toàn văn)

Thông tin tài liệu

CHAPTER 5  PARALLELIZATION AND THREADING ENHANCEMENTS 106 Tasks Task is a new class that represents the work you want completed. There are methods to create, schedule, and synchronize tasks in your application. Task Scheduler All the complexity of working with tasks is handled by the task scheduler, which in turn works with the main .NET thread pool. You can think of tasks as a wrapper for the thread pool and the preferred way of scheduling threads (although there is some additional overhead). The existing thread pool methods will continue to work, but tasks are much easier to use and have additional functionality. So how does the task scheduler work? 1. When tasks are created, they are added to a global task queue. 2. The thread pool will create a number of “worker” threads. The exact number that are created depends on a number of factors such as the number of cores on the machine, current work load, type of work load, and so on. The thread pool utilizes a hill-climbing algorithm that dynamically adjusts the thread pool to use the optimum number of threads. For example, if the thread pool detects that many threads have an I/O bottleneck, it will create additional threads to complete the work more quickly. The thread pool contains a background thread that checks every 0.5 seconds to see whether any work has been completed. If no work has been done (and there is more work to do), a new thread will be created to perform this work. 3. Each worker thread picks up tasks from the global queue and moves it onto its local queue for execution. 4. Each worker thread processes the tasks on its queue. 5. If a thread finishes all the work in its local queue, it steals work from other queues to ensure that work is processed as quickly as possible. Note that tasks will steal work from the end of the other task’s queues to minimize the chance that the task has started operating with the work already. 6. Figure 5-3 demonstrates this process. CHAPTER 5  PARALLELIZATION AND THREADING ENHANCEMENTS 107 Figure 5-3. Overview of task manager Creating a New Task Tasks are very easy to schedule and I think more intuitive than working with traditional threading and the thread pool. There are a number of ways to create a new task, but before you see them, you need to add the following using directive because all the task functionality is found in the System.Threading.Tasks namespace: using System.Threading.Tasks; The easiest way to create a task is with the Task.Factory.StartNew() method. This method accepts an Action delegate and immediately starts the task when created. Task task1 = Task.Factory.StartNew(() => Console.WriteLine("hello task 1")); Another way to create a task is to pass the code you want run into the task’s constructor. The main difference with this method is that you have to explicitly start the task when using this method. This method could be useful for scenarios in which you don’t want the task to run as soon as it is declared: Task task2 = new Task(() => Console.WriteLine("hello task 2")); task2.Start(); CHAPTER 5  PARALLELIZATION AND THREADING ENHANCEMENTS 108 Task.Wait() and Task.WaitAll() The Task.Wait() and Task.WaitAll() methods allow you to pause the flow of execution until the tasks you specify have completed their work. The following listing shows an example of using the Wait() method to ensure that task1 has completed and the WaitAll() method to ensure that task2, task3, and task4 have finished before exiting the application: Task task1 = Task.Factory.StartNew(() => Console.WriteLine("hello task 1")); Task task2 = new Task(() => Console.WriteLine("hello task 2")); Task task3 = Task.Factory.StartNew(() => Console.WriteLine("hello task 3")); Task task4 = Task.Factory.StartNew(() => Console.WriteLine("hello task 4")); task2.Start(); task1.Wait(); Task.WaitAll(task2, task3, task4); Figure 5-4 illustrates the waiting process. Figure 5-4. Flow of execution for the Task.Wait() example Task.WaitAny() You can wait for any task to complete with the Task.WaitAny() method. It could be used, for example, if many tasks were retrieving the same data (e.g., the latest Microsoft stock price) from a number of different sources and you didn’t care which individual source you received the information from. Task.WaitAny(task2, task3, task4); CHAPTER 5  PARALLELIZATION AND THREADING ENHANCEMENTS 109 IsCompleted You can see whether a task is completed by querying the IsCompleted property. It returns a Boolean value indicating whether the task has completed its work. while (task1.IsCompleted == false) { Console.WriteLine("Waiting on task 1"); } ContinueWith() It is often necessary to specify that work should be performed in a specific order. This can be declared in a fluent manner with the ContinueWith() method. In previous examples, the tasks occurred out of the order in which they were created. If you want to enforce this order one way, you could use the ContinueWith() method as follows: Task task3 = Task.Factory.StartNew(() => Console.WriteLine("hello task 1")) .ContinueWith((t)=> Console.WriteLine("hello task 2") ) .ContinueWith((t)=> Console.WriteLine("hello task 3") ) .ContinueWith((t)=> Console.WriteLine("hello task 4") ); The ContinueWith() method also accepts a TaskContinuationOptions enumeration that allows you to specify what should occur if a task fails, as well as a number of other situations. The following code calls the stock service with Stocks[1] as a parameter if the previous task failed to run: Task task3 = Task.Factory.StartNew(() => doSomethingBad()) .ContinueWith((t) => System.Diagnostics.Trace.Write("I will be run"), TaskContinuationOptions.OnlyOnFaulted); Do Parallel Loops Create a Thread for Each Iteration? The answer is maybe but not necessarily. Tasks are created in order to perform the work as quick as possible but it is up to the task manager and scheduler to decide the optimum means to achieve this. Returning Values from Tasks You can retrieve a value that has been returned from a task by querying the result property: var data = Task.Factory.StartNew(() => GetResult()); Console.WriteLine("Parallel task returned with value of {0}", data.Result); An alternative method can be used if you are using Task<T> type: Task<string> t = new Task<string>(()=>GetResult()); t.Start(); Console.WriteLine("Parallel task returned with value of {0}", t.Result); CHAPTER 5  PARALLELIZATION AND THREADING ENHANCEMENTS 110 What if the Task Does Not Yet Have a Result? If you try and access the result of a task, and the task has completed its work, the value will be returned as you would expect. If, however, the task has not completed, execution will block until the task has completed. This could slow your application down as the common language runtime (CLR)) waits for a value to be returned. To minimize this, you probably want to run the task as soon as possible before you need access to the actual value. Task Creation Options When you create a task, you can specify hints to the scheduler about how the task should be scheduled using the TaskCreationOptions class: • AttachedToParent: The task is not attached to the parent. • LongRunning: Hints that the task will run for a long time for optimal scheduling. • None: Default scheduling behavior. • PreferFairness: The tasks should be scheduled in the order in which they are created. Task Status Tasks can have the following status: • Cancelled: The task was cancelled before it reached running status or the cancellation acknowledged and completed with no exceptions. • Created: The task was created but not initialized. • Faulted: Completed due to an exception that was not handled. • RanToCompletion: Completed successfully. • Running: The task currently running. • WaitingForActivation: The task waiting to be activated and scheduled. • WaitingForChildrenToComplete: Waiting for child tasks to complete. • WaitingToRun: Scheduled but not yet run. Overriding TaskScheduler When tasks are created, they are scheduled using the default implementation of the TaskScheduler class (TaskScheduler.Default). TaskScheduler is abstract and can be overridden if you want to provide your own implementation. CHAPTER 5  PARALLELIZATION AND THREADING ENHANCEMENTS 111 Scheduling on UI thread TaskScheduler supports the ability to schedule items on the UI thread, saving you from writing some tedious marshalling code. For more info on this please refer to http://blogs.msdn.com/pfxteam/ archive/2009/04/14/9549246.aspx. Parallel Debugging Enhancements Writing parallel and threaded applications is hard. To help, Microsoft has added additional debugging features to the Visual Studio IDE (premium versions include additional profiling features). To demonstrate these features, we will create a new simple console application. Create a new project called Chapter5.Debugging and enter the following code: using System.Threading.Tasks; static void Main(string[] args) { Task task1 = Task.Factory.StartNew(() => startAnotherTask()); Task task2 = Task.Factory.StartNew(() => startAnotherTask()); Task task3 = Task.Factory.StartNew(() => doSomething()); Console.ReadKey(); } static void startAnotherTask() { Task task4 = Task.Factory.StartNew(() => doSomethingElse()); } static void doSomething() { System.Threading.Thread.Sleep(500000); } static void doSomethingElse() { System.Threading.Thread.Sleep(500000); } Put a breakpoint on the line that reads as follows: Task task3 = Task.Factory.StartNew(() => doSomething()); The first feature we will look at is the Parallel Task window. Parallel Task Window This window shows you all the tasks that are currently running and contains features for filtering and jumping directly to where the task is declared. Run the application in debug mode, ensuring that you have added a breakpoint to the first line. When the breakpoint is hit on the main menu, go to DebugWindowsParallel Tasks (Ctrl+Shift+D+K) . archive/ 200 9/ 04 / 14/ 9 549 246 .aspx. Parallel Debugging Enhancements Writing parallel and threaded applications is hard. To help, Microsoft has added additional debugging features to the Visual Studio. startAnotherTask() { Task task4 = Task.Factory.StartNew(() => doSomethingElse()); } static void doSomething() { System.Threading.Thread.Sleep( 500 000 ); } static void doSomethingElse(). System.Threading.Thread.Sleep( 500 000 ); } static void doSomethingElse() { System.Threading.Thread.Sleep( 500 000 ); } Put a breakpoint on the line that reads as follows: Task task3 = Task.Factory.StartNew(()

Ngày đăng: 01/07/2014, 21:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan