LaboratoryTasks
The first lab with Tasks in C#
- First Tasks [0,5 pkt.]
- Create a solution with the FirstTasks project
- Rewrite or Copy paste the following code:
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace FirstTasks { class Program { private const int iterNo = 10; static void Main(string[] args) { Task t1 = new Task(() => { Random rand = new Random(Task.CurrentId.Value);//init random generator by currentId as a seed Console.WriteLine($"Thread id {Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(rand.Next(0, 100)); for (int i = 0; i < iterNo; i++) { Console.Write($"#{i}# "); Thread.Sleep(rand.Next(500)); } Console.WriteLine($"\nTask {Task.CurrentId.Value} finished"); }); t1.Start(); Console.WriteLine($"Thread id {Thread.CurrentThread.ManagedThreadId}"); Random rand = new Random(); Thread.Sleep(rand.Next(0, 100)); for (int i = 0; i < iterNo; i++) { Console.Write($"{{{i}}} "); Thread.Sleep(rand.Next(500)); } Console.WriteLine("\nMain task finished"); } } } - Task 1 and Main Task print numbers to the screen at random intervals. At the end, each task prints a message about completed work. Unfortunately, the message from Task 1 is not always visible. Find a solution to this problem.
- The task created from Action [0,5 pkt.]
- Add a
static void task2()function to the above program that performs the same job as task t1, with the difference that the iteration number will be framed in square brackets. For example [0],[1],[2]...etc.. - Task t1 was created using lambda notation (anonymously). Create task t2 that implements the
void task2()action. - Start t2 immediately after creation.
- Wait for t2 just after t1.
- Add a
- Passing a parameter [0,5 pkt.]
- Based on the task2 action, create a
static void task3(object o)action. - Inside the task3 action, cast object o to an int variable and use it instead of iterNo (the number of iterations in the loop)
- The task3 action is supposed to display the number of iterations in round brackets, i.e. (0), (1), (2),... etc.
- Create task t3 using the task3 action passing the number of iterations through the parameter.
- Start t3 right after t2
- Wait for t3 right after t2
- Based on the task2 action, create a
- Passing a tuple [0,5 pkt.]
- Add the following action to the program
static void task4(object arg) { (int id, string name) tupleArg = ((int id, string name))arg; //cast tuple values string taskName = tupleArg.name; int taskId = tupleArg.id; Console.WriteLine($"I'm {taskName} and have ID: {taskId}"); } - Create and start a task as follows
(int id, string name) idName = (4, "Task4"); //tupple Task t4 = new Task(task4,idName); t4.Start(); - Task 4 uses a tuple (a variable with multiple values). This is a quick way to pass a few parameters without having to define a class and create an object of it.
- You can also pass the tuple directly to the task:
Task t4b = new Task(task4,(4, "Task4b")); t4b.Start(); - Add wait for t4 right after waiting for t3
- Add the following action to the program
- Passing an object of a defined class [0,5 pkt.]
- Create the MyParam class
public class MyParam { public string Name { get; set; } public int Id { get; set; } } - Create a task5 action that does the same thing as task4 but retrieves data from the passed object (remember to cast to the MyParam class.)
- Create a myParam object of the MyParam class and initialize the Name and Id fields
- Create task t5 that performs the task5 action, pass the myParam object
- Start task t5
- Add waiting for t5 after waiting for t4
- Create the MyParam class
- Creating a list of tasks [0,5 pkt.]
- Declare and set the variable
int taskNo = 5;This will be the number of tasks to run. - Create list
List<Task> t5list = new List<Task>(); - In the loop, create and add taskNo tasks that perform the task5 action. Each task should have an id consistent with the loop iteration number and a name in the form
"Task" + i.ToString() - Created tasks start immediately after being added to the list (in iteration of the loop)
- You can use
Task.Factory.StartNewto return a created and started task. - Add waiting for all tasks (foreach loop) after waiting for t5.
- Declare and set the variable
- The Snow project [0,5 pkt.]
- Add a new Snow project. copy the Star() method code below.
static void Star(object o) { int height = 26; int width = 79; int delay = 200; int orgx; int orgy; ConsoleColor orgcolor; int prevx; int currentx; int prevy = 0; int currenty=0; int iterations = 5; //how many times sars wrap the screen verticaly ConsoleColor? color = null; //if nul then random Random rand = new Random((int)DateTime.Now.Ticks);This is an Action that displays a falling colored star. When you reach the edge of the console, an asterisk appears on the other side.
// Console.WriteLine($"Task started on thread Id {Thread.CurrentThread.ManagedThreadId}"); currentx = prevx = rand.Next(width - 1); Console.CursorVisible = false; //we don't need blinking cursor for (int y = 0; y < height*iterations; y++) { currenty = y % height; //just from interation currentx = prevx + rand.Next(-1,1); if (currentx < 0) currentx = width; if (currentx > width) currentx = 0; lock (Console.Out) { //remember orginal position and color orgx = Console.CursorLeft; orgy = Console.CursorTop; orgcolor = Console.ForegroundColor; //erease elier star Console.SetCursorPosition(prevx, prevy); Console.Write(' '); //set color and new position if (color == null) Console.ForegroundColor = (ConsoleColor)rand.Next(15); else Console.ForegroundColor = color.Value; Console.SetCursorPosition(currentx, currenty); //put the star Console.Write('*'); //restore position and color Console.SetCursorPosition(orgx, orgy); Console.ForegroundColor = orgcolor; } prevx = currentx; prevy = currenty; Thread.Sleep(delay); } } - Create a list of 50 started tasks with the Star action. The object being passed may be null for now.
- Wait for all tasks using the Task.WaitAll method
- Add a new Snow project. copy the Star() method code below.
- More snow. [0,5 pkt]
- If the snowflakes don't all appear at once, uncomment the line
and see how many tasks are running at the same time. - Change the number of threads in the pool. Before starting, add the line
ThreadPool.SetMinThreads(64, 64); - If snowflakes appear in avalanches. Add a random delay from 0 to 100ms before each task creation.
- If the snowflakes don't all appear at once, uncomment the line
- Providing information to Star Action [0,5 pkt.]
- Create a StarParameter class containing variables such as:
- Random rand
- int iterations
- ConsoleColor? color
- Before creating a task, create an object of the StarParameter class with a given number of iterations, a random color and a reference to the Random class object.
- Pass objects to tasks then cast and read data from them.
- Create a StarParameter class containing variables such as:
- Additional activities [0,5 pkt.]
- Secure the random to be threadsafe. (Rand.Shared was introduced in .net 6, it does not require creating an instance and is thread safe by default)
- The Star action should read the current console size and adjust the calculations so that snow falls on the entire screen, even when the window is enlarged.
