Laboratory 9
Task 3 and Parallel operations
- Getting Started [0.5 pts]
- Create a new solution with, a .NET Core console project.
- Demonstrate the functionality of the following function:
private static Task<int[]> calculateSomethingAsync(int size) { return Task.Factory.StartNew<int[]>((s) => { if (s==null) { throw new ArgumentNullException(nameof(s)); } int[] result = new int[(int)s]; for (int i = 0; i < (int)s; i++) { Thread.SpinWait(30000000); result[i] = Random.Shared.Next(10); Console.WriteLine($"I calculated element {i} as [{result[i]}]"); } return result; },size); }
- Progress Reporting [0.5 pts]
- Overload the above function so that instead of the message "I calculated element...", it reports using the
IProgress<(int,int)>
interface. - Include the possibility of passing null instead of Progress.
- Demonstrate the functionality by adding a handler for the
ProgressChanged
event, printing the iteration number and the generated value.
- Overload the above function so that instead of the message "I calculated element...", it reports using the
- Cancellation [0.5 pts]
- Add the ability to cancel the above method using a
CancellationToken
. - The method should check at each iteration if a cancellation request has been made and throw an exception with an appropriate message, e.g., "Cancellation requested".
- Run the application and test the cancellation using
CancelAfter(5000)
(from aCancellationTokenSource
object). This will request cancellation after 5 seconds. - In Main method, catch the generated exception. You can use
AggregateException.Flatten()
.
- Add the ability to cancel the above method using a
- Optional use of continueWith [0.5 pts]
- On the created task from the
calculateSomethingAsync
method, executeContinueWith
in case of an error (TaskContinuationOptions.NotOnRanToCompletion
). This will create an alternative task, let's call itonFaultTask
. - Print the error message passed from the predecessor.
- Similarly, using
ContinueWith
, create a task that displays the contents of the returned array but only in case of successful completion (TaskContinuationOptions.OnlyOnRanToCompletion
). - Wait for both tasks using
Task.WaitAll
. Here, creating an array of both tasks is required. - Catch the exception thrown by the alternative task.
- Test by commenting/uncommenting
CancelAfter(5000)
.
- On the created task from the
- Using ParallelFor [0.5 pts]
- Create a new project.
- Create a simple single-threaded program that generates an array with 10 million random elements.
- You can use the method
static int[] GenerateRandomArray(int size)
{
Random random = new Random();
int[] array = new int[size];
for (int i = 0; i < size; i++)
{
array[i] = random.Next(10);
}
return array;
} - Sum all elements using a single-threaded Linq expression
foreach (int number in numbers) sum += number;
- Measure the execution time.
- Based on the above, conduct experiments with parallel summation using: [1 pt.]
Parallel.ForEach(numbers, number => sum += number);
Measure the time and check if the sum is identical..- Make secure the summation using a lock. Measure the time, check the correctness of the results.
- Perform summation using the single-threaded Linq method
numbers.Sum(number => number);
Measure the time, check the correctness of the results. - Do the same for the PLINQ query
numbers.AsParallel().ForAll(number => sum += number);
Measure the time, check the correctness of the results. - Make secure the above calculations using a lock. Measure the time, check the correctness of the results.
- Perform summation using the sum from PLINQ in two ways:
numbers.AsParallel().Sum(number => number);
numbers.AsParallel().Sum();
- Measure the time and check the correctness of the results. However, do this by running the program with the first case, then with the second, and then with both. Compare the results.
- Perform summation on regular tasks [0.5 pts.]
- To read the number of processors, use
Environment.ProcessorCount
. - Wait for the tasks to complete and sum their results.
double[] partialResults = Task.WhenAll(tasks).Result;
sum = partialResults.Sum(); - Of course, measure the time and verify the correctness of the data.
- To read the number of processors, use
- Summation with calculation [1 pt.]
- Perform all tests for the example from points 6 and 7, but sum the results of the function
static double calculatedValue(double value)
{
return (Math.Sin(Math.Sin(value * value) * Math.Cos(value * value) / Math.PI) * Math.Sin(Math.Sin(value * value) * Math.Cos(value * value) / Math.PI)) > 1 ? 0 : 1; //finally it always returns 1 to simplify checking
} - For example, for a single-threaded operation:
foreach (int number in numbers)
{
sum += calculatedValue(number);
}
- Perform all tests for the example from points 6 and 7, but sum the results of the function