Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная параллельные вычисления.docx
Скачиваний:
7
Добавлен:
27.09.2019
Размер:
938 Кб
Скачать
☆
      1. Figure 7

      1. Output from running several Tasks in parallel

Task 2 – Using the Wait() and WaitAll() Methods

    1. The benefit of executing tasks in parallel is faster execution and the ability to leverage multi-core processors. However, you should also notice that the current implementation introduces the possibility the main application could exit before the thread processing the task finishes.

    2. You can handle this possible situation by invoking the Wait() method on the individual Task objects. This causes the main thread to wait until the indicated tasks are complete before continuing on to the next instruction.

    1. Replace the current method calls from Main(), with a call to Ex2Task2_WaitHandling(). This code will add wait handling to your example.

      1. C#

      1. static void Main(string[] args)

      2. {

      3. ...

      4. // Methods to call

      5. Ex2Task2_WaitHandling();

      6. ...

      7. }

      1. Visual Basic

      1. Sub Main(ByVal args() As String)

      2. ...

      3. ' Methods to call

      4. Ex2Task2_WaitHandling()

      5. ...

      6. End Sub

    1. Add the Ex2Task2_WaitHandling() method to Program.cs (C#) or Module1.vb (Visual Basic):

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task2_WaitHandling CSharp)

      1. C#

      1. private static void Ex2Task2_WaitHandling()

      2. {

      3. Task task1 = Task.Factory.StartNew(delegate

      4. { PayrollServices.GetPayrollDeduction(employeeData[0]); });

      5. Task task2 = Task.Factory.StartNew(delegate

      6. { PayrollServices.GetPayrollDeduction(employeeData[1]); });

      7. Task task3 = Task.Factory.StartNew(delegate

      8. { PayrollServices.GetPayrollDeduction(employeeData[2]); });

      9. task1.Wait();

      10. task2.Wait();

      11. task3.Wait();

      12. }

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task2_WaitHandling VB)

      1. C#

      1. Private Sub Ex2Task2_WaitHandling()

      2. Dim task1 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(0)))

      3. Dim task2 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(1)))

      4. Dim task3 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(2)))

      5. task1.Wait()

      6. task2.Wait()

      7. task3.Wait()

      8. End Sub

    1. Build and run the application.

    2. You should observe that this time all three Tasks completed before the final time was reported, indicating the end of the main thread.

      1. Figure 8

      1. Output from running tasks in parallel with individual Wait() conditions

      1. Note: The main thread waited for the created Task objects to complete before continuing operation. This approach is much simpler and cleaner than using ThreadPool.QueueUserWorkItem, which involves the creation and management of manual reset events, possible with the addition of Interlocked operations as well.

    1. In addition to the Wait() method on the individual Task objects, the static Task class also offers a WaitAll() method allowing you to wait on a specified list of tasks with one call. To see this method in action, remove the individual calls to Wait() for task1, task2, and task3 and replace them with the following:

      1. C#

      1. static void Main(string[] args)

      2. {

      3. ...

      4. // Methods to call

      5. Ex2Task2_WaitHandlingWaitAll();

      6. ...

      7. }

      1. Visual Basic

      1. Sub Main(ByVal args() As String)

      2. ...

      3. ' Methods to call

      4. Ex2Task2_WaitHandlingWaitAll()

      5. ...

      6. End Sub

    1. Add the Ex2Tas2_WaitHandlingWaitAll() method to Program.cs (C#) or Module1.vb (Visual Basic):

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task2_WaitHandlingWaitAll CSharp)

      1. C#

      1. private static void Ex2Task2_WaitHandlingWaitAll()

      2. {

      3. Task task1 = Task.Factory.StartNew(delegate

      4. { PayrollServices.GetPayrollDeduction(employeeData[0]); });

      5. Task task2 = Task.Factory.StartNew (delegate

      6. { PayrollServices.GetPayrollDeduction(employeeData[1]); });

      7. Task task3 = Task.Factory.StartNew (delegate

      8. { PayrollServices.GetPayrollDeduction(employeeData[2]); });

      9. Task.WaitAll(task1, task2, task3);

      10. }

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task2_WaitHandlingWaitAll VB)

      1. Visual Basic

      1. Private Sub Ex2Task2_WaitHandlingWaitAll()

      2. Dim task1 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(0)))

      3. Dim task2 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(1)))

      4. Dim task3 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(2)))

      5. Task.WaitAll(task1, task2, task3)

      6. End Sub

    1. Build and run the application.

    2. You should observe the main application waits until all individual Tasks are completed before continuing.

      1. Figure 9

      1. Output from running tasks in parallel with the WaitAll() method

Task 3 – Using the IsCompleted Property

    1. There will be times when you want to check on the completion status of a Task before doing other work (for instance, you may have another task to run that is dependent on the first task completing first), but you may not want to utilize the Wait() method because Wait() blocks execution on the thread you’ve launched your Task from. For these situations, the Task class exposes an IsCompleted property. This enables you to check whether Task objects have completed their work before you continue with other processing.

    1. Replace the current method calls from Main(), with a call to Ex2Task3_TaskIsCompleted().

      1. C#

      1. static void Main(string[] args)

      2. {

      3. ...

      4. // Methods to call

      5. Ex2Task3_TaskIsCompleted();

      6. ...

      7. }

      1. Visual Basic

      1. Sub Main(ByVal args() As String)

      2. ...

      3. ' Methods to call

      4. Ex2Task3_TaskIsCompleted()

      5. ...

      6. End Sub

    1. Add the Ex2Task3_TaskIsCompleted() method to Program.cs (C#) or Module1.vb (Visual Basic):

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task3_TaskIsCompleted CSharp)

      1. C#

      1. private static void Ex2Task3_TaskIsCompleted()

      2. {

      3. Task task1 = Task.Factory.StartNew(delegate

      4. { PayrollServices.GetPayrollDeduction(employeeData[0]); });

      5. while (!task1.IsCompleted)

      6. {

      7. Thread.Sleep(1000);

      8. Console.WriteLine("Waiting on task 1");

      9. }

      10. Task task2 = Task.Factory.StartNew(delegate

      11. { PayrollServices.GetPayrollDeduction(employeeData[1]); });

      12. while (!task2.IsCompleted)

      13. {

      14. Thread.Sleep(1000);

      15. Console.WriteLine("Waiting on task 2");

      16. }

      17. Task task3 = Task.Factory.StartNew(delegate

      18. { PayrollServices.GetPayrollDeduction(employeeData[2]); });

      19. while (!task3.IsCompleted)

      20. {

      21. Thread.Sleep(1000);

      22. Console.WriteLine("Waiting on task 3");

      23. }

      24. }

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task3_TaskIsCompleted VB)

      1. Visual Basic

      1. Private Sub Ex2Task3_TaskIsCompleted()

      2. Dim task1 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(0)))

      3. Do While Not task1.IsCompleted

      4. Thread.Sleep(1000)

      5. Console.WriteLine("Waiting on task 1")

      6. Loop

      7. Dim task2 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(1)))

      8. Do While Not task2.IsCompleted

      9. Thread.Sleep(1000)

      10. Console.WriteLine("Waiting on task 2")

      11. Loop

      12. Dim task3 As Task = Task.Factory.StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(2)))

      13. Do While Not task3.IsCompleted

      14. Thread.Sleep(1000)

      15. Console.WriteLine("Waiting on task 3")

      16. Loop

      17. End Sub

    1. Build and run the application.

    2. You should observe that Tasks two and three do not start until the previous Task’s IsCompleted property is true.

      1. Figure 10

      1. Output from running tasks in parallel and utilizing the IsCompleted property

Task 4 – Using the ContinueWith() Method

    1. While the IsCompleted property is useful for polling a Task to see if it is finished in order to be able to fire off more work, the Task class offers an even more convenient option. Using the ContinueWith() method makes it easy to string tasks together to run in a specific order.

    2. The functionality passed in as arguments to the ContinueWith() method will be executed once the Task object’s logic continues.

    1. Replace the current method calls from Main(), with a call to Ex2Task4_ContinueWith().

      1. C#

      1. static void Main(string[] args)

      2. {

      3. ...

      4. // Methods to call

      5. Ex2Task4_ContinueWith();

      6. ...

      7. }

      1. Visual Basic

      1. Sub Main(ByVal args() As String)

      2. ...

      3. ' Methods to call

      4. Ex2Task4_ContinueWith()

      5. ...

      6. End Sub

    1. Add the Ex2Task4_ContinueWith() method to Program.cs (C#) or Module1.vb (Visual Basic):

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task4_ContinueWith CSharp)

      1. C#

      1. private static void Ex2Task4_ContinueWith()

      2. {

      3. Task task3 = Task.Factory.StartNew(delegate

      4. { PayrollServices.GetPayrollDeduction(employeeData[0]); })

      5. .ContinueWith(delegate

      6. { PayrollServices.GetPayrollDeduction(employeeData[1]); })

      7. .ContinueWith(delegate

      8. { PayrollServices.GetPayrollDeduction(employeeData[2]); });

      9. task3.Wait();

      10. }

      1. (Code Snippet – Intro to Parallel Extensions Lab - Ex2 Ex2Task4_ContinueWith VB)

      1. Visual Basic

      1. Private Sub Ex2Task4_ContinueWith()

      2. Dim task3 As Task = Task.Factory _

      3. .StartNew(Sub() PayrollServices.GetPayrollDeduction(employeeData(0))) _

      4. .ContinueWith(Sub() PayrollServices.GetPayrollDeduction(employeeData(1))) _

      5. .ContinueWith(Sub() PayrollServices.GetPayrollDeduction(employeeData(2)))

      6. task3.Wait()

      7. End Sub

      1. Note: Here you created the first Task as normal, but you used the ContinueWith() method to have the runtime execute the subsequent calls in order.

    1. Build and run the application.

    2. You should observe that the tasks execute in order – employee 1 first, followed by employee 2, and finally employee 3.