Introduction to Tasks
Introduction to Tasks
A Task
Introduction
At this time, we know that, to get an application working in a computer, you create one or more threads. Each thread is in charge of performing a particular operation. Such an operation is called a task.
Practical Learning: Introducing Tasks
using System; namespace RedOakHighSchool1 { public class AcademicsManagement { private static int number = -1; public static int Main(string[] args) { int iCourse1Sem1NumericGrade = 0; int iCourse2Sem1NumericGrade = 0; int iCourse3Sem1NumericGrade = 0; Console.Title = "Red Oak High School"; Console.WriteLine("Red Oak High School"); Console.WriteLine("==================================="); Console.WriteLine("Type the grades for the 1st semester"); Console.Write("Algebra 1: "); iCourse1Sem1NumericGrade = int.Parse(Console.ReadLine()); Console.Write("English: "); iCourse2Sem1NumericGrade = int.Parse(Console.ReadLine()); Console.Write("Social Science: "); iCourse3Sem1NumericGrade = int.Parse(Console.ReadLine()); number = iCourse1Sem1NumericGrade; Func<char> GetCourse2LetterGrade = () => { if (iCourse2Sem1NumericGrade >= 90) return 'A'; else if (iCourse2Sem1NumericGrade >= 80) return 'B'; else if (iCourse2Sem1NumericGrade >= 70) return 'C'; else if (iCourse2Sem1NumericGrade >= 65) return 'D'; return 'F'; }; Console.WriteLine("==================================="); return 0; } private static char GetCourse1LetterGrade() { if (number >= 90) return 'A'; else if (number >= 80) return 'B'; else if (number >= 70) return 'C'; else if (number >= 65) return 'D'; return 'F'; } } }
Synchronous Operations
Imagine you have one line of trains on a single set of rails between two locations. In one location, you assemble and produce some objects, such as vehicles, that you must ship to the other location where they are sold at a car dealership:
Since you have only one line of trains, only one train can travel at a time to deliver the products from the starting point to the other. Only one train at a time can start from the manufacturer. If many trains must travel from the manufacturer, only one must start. The next train would start only after the previous one has left. In this type of scenario, one operation (a train leaving the station) must complete before the next (similar) operation starts (before the next train leaves the station). Your business operating with one line of trains would be called a single-threaded application. This is referred to as a synchronous operation.
Introduction to Asynchronous Operations
With only one line of trains, you can make only one delivery. Each train must wait for the one ahead to leave. Because your employees must keep track of all the movements of all trains and avoid accidents, one of the things they must do is to always block many of the operations in order to conduct one particular operation. In fact, if something bad, such as an accident, happens to the running train, everything must stop until the problem is addressed or fixed. This can slow your business and make merchandise delivery take too much time.
Imagine your business starts growing. One, and probably the best, thing you can do to deliver more products (and consequently work faster) is to have more than one line of trains. That way, different trains carrying merchandise can leave the manufacturer at the same time. In fact, you can have as many trains leaving the manufacturer as train lines are available:
In fact also, different trains can leave at different times:
This means that the departing and/or the activities of one train don’t depend on another train. In fact, even if one train is having problems, such as an accident, on one line, the other trains would still operate. You can also distribute work. For example, you can:
Introduction to Task Procedures
An Action Task
Some operations on a computer use a lot of resources and some operations take a long time to complete. One of the consequences is that one operation could block resources or processing time that other operations may need. One of the ways you can make operations run faster in your project is to run many operations at the same time. This concept certainly also applies when various users, using various browsers, different browsers, or various tabs at the same time, try to access the same webpage, the same video of a website (actually the webserver), the same database, the same file, etc. To eliminate or reduce the likelihood of operations interfering with each other, we saw that you create threads and run each thread on its own area of of work. This means that the threads, or various operations, are running asynchronously. To make this possible, the .NET Framework provides the concepts of tasks.
A task is an operation that runs in a manner that it would not interfere with other operations (that is, other tasks) on the same computer. This means that a task is an operation that runs asynchronously. Compared to functions (or methods of a class), the .NET Framework provides two categories of tasks: those that don't produce a result (also called procedures) and those that return a value or an object (also called functions).
To support tasks, that is, to allow you to create one or more tasks, the .NET Framework provides a class named Task. This class is defined in the System.Threading.Tasks namespace.
The Task class uses many constructors for different goals. The simplest constructor uses the following syntax:
public Task(Action action);
This version of the Task constructor takes a void method as argument. You can pass the name of the method as argument. Here is an example:
using System.Threading.Tasks; public delegate double Operation(double a, double b); public class Exercise { public static void Main() { Task wisdom = new Task(Proverb); } private void Proverb() { } }
You can also define the method directly where it is needed. Here is an example:
using System.Threading.Tasks;
public class Exercise
{
public static void Main()
{
Task wisdom = new Task(() =>
{
});
}
}
Practical Learning: Creating Tasks
using System;
using System.Threading.Tasks;
namespace RedOakHighSchool1
{
public class AcademicsManagement
{
private static int number = -1;
public static int Main(string[] args)
{
. . .
Task<char> processCourse1Sem1NumericGrade = new Task<char>(GetCourse1LetterGrade);
Task<char> processCourse2Sem1NumericGrade = new Task<char>(GetCourse2LetterGrade);
Task<char> processCourse3Sem1NumericGrade = new Task<char>(() =>
{
if (iCourse3Sem1NumericGrade >= 90)
return 'A';
else if (iCourse3Sem1NumericGrade >= 80)
return 'B';
else if (iCourse3Sem1NumericGrade >= 70)
return 'C';
else if (iCourse3Sem1NumericGrade >= 65)
return 'D';
return 'F';
});
Console.WriteLine("===================================");
return 0;
}
. . .
}
}
Starting a Task
After creating a task, you can launch its operation. To support this, the Task class is equipped with a method named Start. It is overloaded with two versions. The simplest version uses the following syntax:
public void Start();
Simply call this method to perform the task. Here is an example:
using static System.Console;
using System.Threading.Tasks;
public class Exercise
{
public static int Main()
{
Task wisdom = new Task(TurkishProverb);
wisdom.Start();
return 0;
}
private static void TurkishProverb()
{
WriteLine("A tree won't fall with a single blow");
}
}
Practical Learning: Starting some Tasks
using System;
using System.Threading.Tasks;
namespace RedOakHighSchool1
{
public class AcademicsManagement
{
private static int number = -1;
public static int Main(string[] args)
{
. . .
Task<char> processCourse1Sem1NumericGrade = new Task<char>(GetCourse1LetterGrade);
Task<char> processCourse2Sem1NumericGrade = new Task<char>(GetCourse2LetterGrade);
Task<char> processCourse3Sem1NumericGrade = new Task<char>(() =>
{
if (iCourse3Sem1NumericGrade >= 90)
return 'A';
else if (iCourse3Sem1NumericGrade >= 80)
return 'B';
else if (iCourse3Sem1NumericGrade >= 70)
return 'C';
else if (iCourse3Sem1NumericGrade >= 65)
return 'D';
return 'F';
});
processCourse1Sem1NumericGrade.Start();
processCourse2Sem1NumericGrade.Start();
processCourse3Sem1NumericGrade.Start();
Console.WriteLine("===================================");
return 0;
}
. . .
}
}
Running a Task
In the above code, we first defined a task before starting it. As an alternative, the Task class provides an overloaded method named Run. It is available in various versions for different goals. Consider the following code:
using static System.Console;
using System.Threading.Tasks;
public class Exercise
{
public static int Main()
{
Task warning = new Task(SocialScience);
warning.Start();
return 0;
}
public static void SocialScience()
{
WriteLine("When you commit a suicide, the worse thing that can happen to you is that you don't die.");
}
}
To call the Task.Run() method, you don't have to first create a method for the task. You can call the Task.Run() method as a combination of defining the method and starting it. You can first define a local Action expression, then pass its name as argument. Here is an example:
using static System.Console;
using System.Threading.Tasks;
public class Exercise
{
public static int Main()
{
Action sayit = () =>
{
WriteLine("When you commit a suicide, the worse thing that can happen to you is that you don't die.");
};
Task warning = Task.Run(sayit);
return 0;
}
}
Alternatively, you can create a lambda expression in the parentheses of the method. Here is an example:
using static System.Console;
using System.Threading.Tasks;
public class Exercise
{
public static int Main()
{
Task warning = Task.Run(() =>
{
WriteLine("When you commit a suicide, the worse thing that can happen to you is that you don't die.");
});
return 0;
}
}
A Procedural Task as a Type
A Task object can be used as a type. This means that you can create a method that takes a task as argument. In the same way, a method can return a task. Here is an example:
using static System.Console; using System.Threading.Tasks; public class Exercise { public static int Main() { Task something = Visit(); something.Start(); return 0; } private static Task Visit() { Task wisdom = new Task(() => { WriteLine("Thank you for your visit"); }); return wisdom; } }
Introduction to Functional Tasks
A Functional Task
As seen with functions in previous lessons, some operations must produce a value. That's the case for methods that return a value or an object. To support tasks that produce a value, the .NET Framework provides a generic Task<> class. In fact, this class inherits from the non-generic Task class:
public class Task<TResult> : Task
Creating a Functional Task
To create a task, declare a variable of the Task<> class. As seen when studying generics, you must specify the parameter type. In this case, this is the type returned by the function. The parameter type can be a primitive (number-based, character, Boolean) or a string. It can also be a class type.
To let you initialize a task, the Task<> class is equipped with various constructors. The simples constructor uses the following syntax:
public Task(Func<TResult> function);
This constructor takes a function (a method that returns a value) as argument. The function doesn't take any argument but it must return any value you want. You can first define a method and pass its name as the argument to the above constructor. Here is an example:
using static System.Console; using System.Threading.Tasks; public class Academics { private static int number = 88; public static int Main() { Task<char> courseGradeProcessing = new Task<char>(GetLetterGrade); return 0; } public static char GetLetterGrade() { if (number >= 90) return 'A'; else if (number >= 80) return 'B'; else if (number >= 70) return 'C'; else if (number >= 65) return 'D'; return 'F'; } }
Alternatively, you can define the function as a Func<> object and then pass its name to the constructor. Here is an example:
using System; using System.Threading.Tasks; public class Academics { public static int Main() { int number = 88; Func<char> GetLetterGrade = () => { if (number >= 90) return 'A'; else if (number >= 80) return 'B'; else if (number >= 70) return 'C'; else if (number >= 65) return 'D'; return 'F'; }; Task<char> courseGradeProcessing = new Task<char>(GetLetterGrade); return 0; } }
One more option is to define the function as a lambda expression in the parentheses of the constructor.
Practical Learning: Creating Tasks
using static System.Console;
using System.Threading.Tasks;
namespace RedOakHighSchool1.Controllers
{
public class Academics
{
private int number = -1;
public static int Main()
{
return 0;
}
public ActionResult StartGradeReport()
{
return 0;
}
public ActionResult GradeReportPreparation(string CourseName1, string Course1Sem1NumericGrade, string Course1Sem2NumericGrade, string Course1Sem3NumericGrade,
string CourseName2, string Course2Sem1NumericGrade, string Course2Sem2NumericGrade, string Course2Sem3NumericGrade,
string CourseName3, string Course3Sem1NumericGrade, string Course3Sem2NumericGrade, string Course3Sem3NumericGrade,
string CourseName4, string Course4Sem1NumericGrade, string Course4Sem2NumericGrade, string Course4Sem3NumericGrade,
string CourseName5, string Course5Sem1NumericGrade, string Course5Sem2NumericGrade, string Course5Sem3NumericGrade)
{
number = int.Parse(Course1Sem1NumericGrade);
int iCourse2Sem1NumericGrade = int.Parse(Course2Sem1NumericGrade);
int iCourse3Sem1NumericGrade = int.Parse(Course3Sem1NumericGrade);
Func<char> GetCourse2LetterGrade = () =>
{
if (iCourse2Sem1NumericGrade >= 90)
return 'A';
else if (iCourse2Sem1NumericGrade >= 80)
return 'B';
else if (iCourse2Sem1NumericGrade >= 70)
return 'C';
else if (iCourse2Sem1NumericGrade >= 65)
return 'D';
return 'F';
};
Task<char> processCourse1Sem1NumericGrade = new Task<char>(GetCourse1LetterGrade);
Task<char> processCourse2Sem1NumericGrade = new Task<char>(GetCourse2LetterGrade);
Task<char> processCourse3Sem1NumericGrade = new Task<char>(() =>
{
if (iCourse3Sem1NumericGrade >= 90)
return 'A';
else if (iCourse3Sem1NumericGrade >= 80)
return 'B';
else if (iCourse3Sem1NumericGrade >= 70)
return 'C';
else if (iCourse3Sem1NumericGrade >= 65)
return 'D';
return 'F';
});
return 0;
}
public char GetCourse1LetterGrade()
{
if (number >= 90)
return 'A';
else if (number >= 80)
return 'B';
else if (number >= 70)
return 'C';
else if (number >= 65)
return 'D';
return 'F';
}
}
}
Introduction to Starting a Functional Task
After creating a task, there are many ways you can launch it. As one way to do this, and as seen for the Task class, the Task<> class inherits the Start() method from its parent.
Practical Learning: Starting a Functional Task
using System; using System.Threading.Tasks; namespace RedOakHighSchool1.Controllers { public class Academics { private int number = -1; public static int Main() { return 0; } public ActionResult StartGradeReport() { return 0; } public ActionResult GradeReportPreparation(string CourseName1, string Course1Sem1NumericGrade, string Course1Sem2NumericGrade, string Course1Sem3NumericGrade, string CourseName2, string Course2Sem1NumericGrade, string Course2Sem2NumericGrade, string Course2Sem3NumericGrade, string CourseName3, string Course3Sem1NumericGrade, string Course3Sem2NumericGrade, string Course3Sem3NumericGrade, string CourseName4, string Course4Sem1NumericGrade, string Course4Sem2NumericGrade, string Course4Sem3NumericGrade, string CourseName5, string Course5Sem1NumericGrade, string Course5Sem2NumericGrade, string Course5Sem3NumericGrade) { number = int.Parse(Course1Sem1NumericGrade); int iCourse2Sem1NumericGrade = int.Parse(Course2Sem1NumericGrade); int iCourse3Sem1NumericGrade = int.Parse(Course3Sem1NumericGrade); Func<char> GetCourse2LetterGrade = () => { if (iCourse2Sem1NumericGrade >= 90) return 'A'; else if (iCourse2Sem1NumericGrade >= 80) return 'B'; else if (iCourse2Sem1NumericGrade >= 70) return 'C'; else if (iCourse2Sem1NumericGrade >= 65) return 'D'; return 'F'; }; Task<char> processCourse1Sem1NumericGrade = new Task<char>(GetCourse1LetterGrade); Task<char> processCourse2Sem1NumericGrade = new Task<char>(GetCourse2LetterGrade); Task<char> processCourse3Sem1NumericGrade = new Task<char>(() => { if (iCourse3Sem1NumericGrade >= 90) return 'A'; else if (iCourse3Sem1NumericGrade >= 80) return 'B'; else if (iCourse3Sem1NumericGrade >= 70) return 'C'; else if (iCourse3Sem1NumericGrade >= 65) return 'D'; return 'F'; }); processCourse1Sem1NumericGrade.Start(); processCourse2Sem1NumericGrade.Start(); processCourse3Sem1NumericGrade.Start(); return 0; } private char GetCourse1LetterGrade() { if (number >= 90) return 'A'; else if (number >= 80) return 'B'; else if (number >= 70) return 'C'; else if (number >= 65) return 'D'; return 'F'; } } }
The Value of a Functional Task
Remember that, unlike the Task object, a Task<int> produces a value. To let you get that value, the Task<int> class is equipped with a property named Result:
public TResult Result { get; }
Practical Learning: Getting the Result of a Task
using System;
using System.Threading.Tasks;
namespace RedOakHighSchool1
{
public class AcademicsManagement
{
private static int number = -1;
public static int Main(string[] args)
{
int iCourse1Sem1NumericGrade = 0;
int iCourse2Sem1NumericGrade = 0;
int iCourse3Sem1NumericGrade = 0;
Console.Title = "Red Oak High School";
Console.WriteLine("Red Oak High School");
Console.WriteLine("===================================");
Console.WriteLine("Type the grades for the 1st semester");
Console.Write("Algebra 1: ");
iCourse1Sem1NumericGrade = int.Parse(Console.ReadLine());
Console.Write("English: ");
iCourse2Sem1NumericGrade = int.Parse(Console.ReadLine());
Console.Write("Social Science: ");
iCourse3Sem1NumericGrade = int.Parse(Console.ReadLine());
number = iCourse1Sem1NumericGrade;
Func<char> GetCourse2LetterGrade = () =>
{
if (iCourse2Sem1NumericGrade >= 90)
return 'A';
else if (iCourse2Sem1NumericGrade >= 80)
return 'B';
else if (iCourse2Sem1NumericGrade >= 70)
return 'C';
else if (iCourse2Sem1NumericGrade >= 65)
return 'D';
return 'F';
};
Task<char> processCourse1Sem1NumericGrade = new Task<char>(GetCourse1LetterGrade);
Task<char> processCourse2Sem1NumericGrade = new Task<char>(GetCourse2LetterGrade);
Task<char> processCourse3Sem1NumericGrade = new Task<char>(() =>
{
if (iCourse3Sem1NumericGrade >= 90)
return 'A';
else if (iCourse3Sem1NumericGrade >= 80)
return 'B';
else if (iCourse3Sem1NumericGrade >= 70)
return 'C';
else if (iCourse3Sem1NumericGrade >= 65)
return 'D';
return 'F';
});
processCourse1Sem1NumericGrade.Start();
processCourse2Sem1NumericGrade.Start();
processCourse3Sem1NumericGrade.Start();
Console.WriteLine("===================================");
Console.WriteLine("Semester 1 - Grades Report");
Console.WriteLine("---------------------------------");
Console.WriteLine("Algebra 1: {0}", processCourse1Sem1NumericGrade.Result);
Console.WriteLine("English: {0}", processCourse2Sem1NumericGrade.Result);
Console.WriteLine("Social Science: {0}", processCourse3Sem1NumericGrade.Result);
Console.WriteLine("===================================");
return 0;
}
private static char GetCourse1LetterGrade()
{
if (number >= 90)
return 'A';
else if (number >= 80)
return 'B';
else if (number >= 70)
return 'C';
else if (number >= 65)
return 'D';
return 'F';
}
}
}
Red Oak High School =================================== Type the grades for the 1st semester Algebra 1:
Red Oak High School =================================== Type the grades for the 1st semester Algebra 1: 92 English: 64 Social Science: 88
Red Oak High School =================================== Type the grades for the 1st semester Algebra 1: 92 English: 64 Social Science: 88 =================================== Semester 1 - Grades Report --------------------------------- Algebra 1: A English: F Social Science: B =================================== Press any key to continue . . .
Running a Functional Task<>
The Task<> class inherits the Run() method from its parent. This gives you various ways to immediately (create and) start a task. When it comes to a generic task, if you want, you can specify the parameter type on the Task object and/or the Run() method.
Practical Learning: Running a Task
using System; using System.Threading.Tasks; namespace RedOakHighSchool1 { public class AcademicsManagement { private static int number = -1; public static int Main(string[] args) { int iCourse1Sem1NumericGrade = 0; int iCourse2Sem1NumericGrade = 0; int iCourse3Sem1NumericGrade = 0; int iCourse4Sem1NumericGrade = 0; int iCourse5Sem1NumericGrade = 0; Console.Title = "Red Oak High School"; Console.WriteLine("Red Oak High School"); Console.WriteLine("==================================="); Console.WriteLine("Type the grades for the 1st semester"); Console.Write("Algebra 1: "); iCourse1Sem1NumericGrade = int.Parse(Console.ReadLine()); Console.Write("English: "); iCourse2Sem1NumericGrade = int.Parse(Console.ReadLine()); Console.Write("Social Science: "); iCourse3Sem1NumericGrade = int.Parse(Console.ReadLine()); Console.Write("Philosophy: "); iCourse4Sem1NumericGrade = int.Parse(Console.ReadLine()); Console.Write("Chemistry: "); iCourse5Sem1NumericGrade = int.Parse(Console.ReadLine()); number = iCourse1Sem1NumericGrade; Func<char> GetCourse2LetterGrade = () => { if (iCourse2Sem1NumericGrade >= 90) return 'A'; else if (iCourse2Sem1NumericGrade >= 80) return 'B'; else if (iCourse2Sem1NumericGrade >= 70) return 'C'; else if (iCourse2Sem1NumericGrade >= 65) return 'D'; return 'F'; }; Task<char> processCourse1Sem1NumericGrade = new Task<char>(GetCourse1LetterGrade); Task<char> processCourse2Sem1NumericGrade = new Task<char>(GetCourse2LetterGrade); Task<char> processCourse3Sem1NumericGrade = new Task<char>(() => { if (iCourse3Sem1NumericGrade >= 90) return 'A'; else if (iCourse3Sem1NumericGrade >= 80) return 'B'; else if (iCourse3Sem1NumericGrade >= 70) return 'C'; else if (iCourse3Sem1NumericGrade >= 65) return 'D'; return 'F'; }); processCourse1Sem1NumericGrade.Start(); processCourse2Sem1NumericGrade.Start(); processCourse3Sem1NumericGrade.Start(); Func<char> GetCourse4LetterGrade = () => { if (iCourse4Sem1NumericGrade >= 90) return 'A'; else if (iCourse4Sem1NumericGrade >= 80) return 'B'; else if (iCourse4Sem1NumericGrade >= 70) return 'C'; else if (iCourse4Sem1NumericGrade >= 65) return 'D'; return 'F'; }; Task<char> processCourse4Sem1NumericGrade = Task<char>.Run<char>(GetCourse4LetterGrade); Task<char> processCourse5Sem1NumericGrade = Task<char>.Run<char>(() => { if (iCourse5Sem1NumericGrade >= 90) return 'A'; else if (iCourse5Sem1NumericGrade >= 80) return 'B'; else if (iCourse5Sem1NumericGrade >= 70) return 'C'; else if (iCourse5Sem1NumericGrade >= 65) return 'D'; return 'F'; }); Console.WriteLine("==================================="); Console.WriteLine("Semester 1 - Grades Report"); Console.WriteLine("---------------------------------"); Console.WriteLine("Algebra 1: {0}", processCourse1Sem1NumericGrade.Result); Console.WriteLine("English: {0}", processCourse2Sem1NumericGrade.Result); Console.WriteLine("Social Science: {0}", processCourse3Sem1NumericGrade.Result); Console.WriteLine("Philosophy: {0}", processCourse4Sem1NumericGrade.Result); Console.WriteLine("Chemistry: {0}", processCourse5Sem1NumericGrade.Result); Console.WriteLine("==================================="); return 0; } private static char GetCourse1LetterGrade() { if (number >= 90) return 'A'; else if (number >= 80) return 'B'; else if (number >= 70) return 'C'; else if (number >= 65) return 'D'; return 'F'; } } }
Red Oak High School =================================== Type the grades for the 1st semester Algebra 1: 73 English: 96 Social Science: 92 Philosophy: 69 Chemistry: 85
Red Oak High School =================================== Type the grades for the 1st semester Algebra 1: 73 English: 96 Social Science: 92 Philosophy: 69 Chemistry: 85 =================================== Semester 1 - Grades Report --------------------------------- Algebra 1: C English: A Social Science: A Philosophy: D Chemistry: B =================================== Press any key to continue . . .
|
||
Previous | Copyright © 2014-2019, FunctionX | Next |
|