Tải bản đầy đủ - 0 (trang)
15-4. Parallel Process a Collection

15-4. Parallel Process a Collection

Tải bản đầy đủ - 0trang

CHAPTER 15 ■ PARALLEL PROGRAMMING



will be determined by the runtime, whereas a value of 1 or more limits the number of tasks that will run

at the same time (a value of 0 will throw an exception).



The Code

The following example creates tasks to process each element of a simple array using the printNumbers

method. We have called Thread.Sleep in this method to slow down the processing so that the example is

clearer. We use the MaxDegreeOfParallelism property of ParallelOptions to ensure that at most two

tasks are performed simultaneously—when running the example, notice that the output from the first

two tasks is intermingled and then followed by the output from the third task.

using System;

using System.Threading;

using System.Threading.Tasks;

namespace Recipe15_04

{

class Recipe15_04

{

static void Main(string[] args)

{

Console.WriteLine("Press enter to start");

Console.ReadLine();

// Define the data we want to process.

int[] numbersArray = { 100, 200, 300 };

// Configure the options.

ParallelOptions options = new ParallelOptions();

options.MaxDegreeOfParallelism = 2;

// Process each data element in parallel.

Parallel.ForEach(numbersArray, options, baseNumber =>

printNumbers(baseNumber));

Console.WriteLine("Tasks Completed.

Console.ReadLine();



Press Enter");



}

static void printNumbers(int baseNumber)

{

for (int i = baseNumber, j = baseNumber + 10; i < j; i++)

{

Console.WriteLine("Number: {0}", i);

Thread.Sleep(100);

}

}

}

}



737



www.it-ebooks.info



CHAPTER 15 ■ PARALLEL PROGRAMMING



15-5. Chain Tasks Together

Problem

You need to perform several tasks in sequence.



Solution

Create an instance of Task for the initial activity using the class constructors (as shown in the previous

recipes in this chapter), and then call the ContinueWith method to create a Task instance representing

the next activity in the sequence. When you have created all of the Task instances you require, call the

Start method on the first in the sequence.



How It Works

The Task.ContinueWith and Task.ContinueWith<> methods create a new task that will continue upon

completion of the Task instance on which they are invoked. The previous task (known as the antecedent)

is provided as an input parameter to the lambda expression in the ContinueWith method—this can be

used to check the states or get the result of the previous task, as shown in the following example.



The Code

The example for this recipe chains three tasks together. The first task adds some integer values. The

second obtains the result from the first and prints it out, and the third task simply writes a message

without reference to the previous tasks at all.

using System;

using System.Threading;

using System.Threading.Tasks;

namespace Recipe15_05

{

class Recipe15_05

{

static void Main(string[] args)

{

Console.WriteLine("Press enter to start");

Console.ReadLine();

// Create the set of tasks.

Task firstTask = new Task(() => sumAndPrintNumbers(100));

Task secondTask = firstTask.ContinueWith(parent => printTotal(parent));

Task thirdTask = secondTask.ContinueWith(parent => printMessage());



738



www.it-ebooks.info



CHAPTER 15 ■ PARALLEL PROGRAMMING



// Start the first task.

firstTask.Start();

// Read a line to keep the process alive.

Console.WriteLine("Press enter to finish");

Console.ReadLine();

}

static int sumAndPrintNumbers(int baseNumber)

{

Console.WriteLine("sum&print called for {0}", baseNumber);

int total = 0;

for (int i = baseNumber, j = baseNumber + 10; i < j; i++)

{

Console.WriteLine("Number: {0}", i);

total += i;

}

return total;

}

static void printTotal(Task parentTask)

{

Console.WriteLine("Total is {0}", parentTask.Result);

}

static void printMessage()

{

Console.WriteLine("Message from third task");

}

}

}



15-6. Write a Cooperative Algorithm

Problem

You need to write a parallel algorithm with multiple phases, each of which must be completed before the

next can begin.



Solution

Create an instance of the System.Threading.Barrier class and call the SignalAndWait method from your

Task code at the end of each algorithm phase.



739



www.it-ebooks.info



CHAPTER 15 ■ PARALLEL PROGRAMMING



How It Works

The Barrier class allows you to wait for a set of tasks to complete one part of an algorithm before moving

onto the next. This is useful when the overall results from the one phase are required by all tasks in order

to complete a subsequent phase. When creating an instance of Barrier, you specify an integer as a

constructor argument. In your Task code, you call the SignalAndWait method when you have reached the

end of a phase—your Task will block until the specified number of Tasks is waiting, at which point the

Barrier allows all of the waiting tasks to continue into the next phase. It is up to you to determine what

constitutes each phase of your algorithm and to specify how many Tasks must reach the barrier before

the next phase can begin.

You can also specify an action to be performed when each phase is completed (i.e., after the

required number of tasks have called the SignalAndWait method, but before the tasks are allowed to

continue to the next phase—the example for this recipe demonstrates how to do this with a lambda

function.



■ Note It is important to ensure that you set the Barrier instance to expect the correct number of tasks at each

stage of your algorithm. If you tell the Barrier to expect too few tasks, one phase may not have completed before

the next begins. If you tell the Barrier to expect too many tasks, a phase will never start, even though all of your

tasks have completed the earlier phase. You can change the number of tasks a Barrier will wait for by using the

AddParticipant, AddParticipants, RemoveParticipant, and RemoveParticipants methods.



The Code

The following example shows a simple two-phase cooperative algorithm, performed by three tasks.

When all of the tasks reach the barrier at the end of each phase, the notifyPhaseEnd method is called.

using System;

using System.Threading;

using System.Threading.Tasks;

namespace Recipe15_06

{

class Recipe15_06

{

static void Main(string[] args)

{

// Create the barrier.

Barrier myBarrier = new Barrier(3,

(barrier) => notifyPhaseEnd(barrier));

Task task1 = Task.Factory.StartNew(

() => cooperatingAlgorithm(1, myBarrier));

Task task2 = Task.Factory.StartNew(

() => cooperatingAlgorithm(2, myBarrier));



740



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

15-4. Parallel Process a Collection

Tải bản đầy đủ ngay(0 tr)

×