-
Notifications
You must be signed in to change notification settings - Fork 1
Day 05 Introduction to TPL
Kobi Hari edited this page Oct 28, 2020
·
1 revision
Fun With Tasks | Introduction to Tasks and TPL |
- We talked about process, as a way for the operating system to allow multiple programs to run
- We talked about the way a process allocates memory to the program
- We talked about Threads, as a way to execute code.
- We talked about App Domains as a middle entity between process and thread, that allows to run multiple programs in the same process, by dividing the memory between the applications while sharing the thread pool and some other resources
- Threads are operating system entities that run code.
- Each thread has an allocated stack, but all threads share the same heap, so the different threads have access to the same memory in additional to a private stack.
- You can create a new thread and run a delegate in it, but this is considered bad practice:
- Thread allocation consumes time and memory
- The more threads there are, the more time in takes to manage them.
- Modren approaches favor thread pooling, which is why .net comes with a Thread Pool with reusable threads.
- You can send a delegate (a work item) to the thread pool
- The thread pool has a global queue for work items
- The thread pool creates new threads according to the workload
- Each thread also has its own queue and the thread pool sends the delegate to the selected thread's queue.
- The thread pool then uses some additional logic to spread the work items smartly between the threads.
- Task is a container of information, it does not run code.
- Task is a container of information, only! it does not run code!!!
- Task object only holds information about the completion of a... well... task.
- Task Members:
- Status - In Progress, Completed, or Failed. Notice that it does not care if the task has started, only if it has ended
- Result - In completed, the result of the task.
- The task data is not meant to be pulled, but rather Pushed.
- You can sign up for the task by using the
ContinueWith
method. This method accepts a delegate, along with other parameters, and runs the delegate upon completion of the task.
- We talk briefly about WPF, XAML and the thread structure of UI frameworks (single main thread that has sole access to the UI, along with thread pool background threads that can not access UI objects)
- We built a small application that takes about 6 seconds to calculate all the prime numbers between 1 and 180000
- We saw that if we perform the caluclations on the main thread, the UI freezes in the meantime
- We used
Task.Factory.StartNew
in order to pass a delegate to the thread pool and create a task over that delegate - We used
Task.ContinueWith
to schedule continuation to the task to be run upon completion - We saw that by default, the continuation runs in the thread pool as well, which caused an exception when we tried to modify UI objects
- We saw that we can tell the continuation to run in the same thread that created the task, by using
TaskScheduler.FromCurrentSynchronizationContext
- We agreed that using these methods explicitly is cumbersome.
- We understood that the keywords
async
andawait
basically tell the compiler to split the method into several methods, and then schedule each part as a continuation of a task - The
async
keyword is reqruired in order to tell the compiler that theawait
keyword is going to be used in the body of the method - The
await
keyword splits the method, and everything that comes after it becomes a continuation method - The method finishes at the first
await
and returns synchronously to the caller - We saw that
ContinueWith
returns a task that describes the completion of the continuation - We saw that
async
methods do the same thing. - We saw the difference between calling an async method with await, and without.
- We talked about Task exception and how important it is to make sure they are
awaited
so the exceptions are caught and treated.
- We continuted to investigate how exceptions work with tasks.
- We learned about the
AggregateException
class that is returned by tasks and understood that the exceptions are always aggragated bacause the task itself is a hierarchic concept - We used
InnerException
andInnerExceptions
properties to get the exceptions that were actually thrown in the task - We used the
Flatten
method to convert the exception hierarchy into a flat list - We saw that
async await
catches the first inner exception, not the aggregate exeption, but we can still access the original exception by using the original task and reading fromTask.Exception
property