-
Notifications
You must be signed in to change notification settings - Fork 1
Day 06 TPL Continued
Kobi Hari edited this page Oct 29, 2020
·
1 revision
Fun With Tasks | Introduction to Tasks and TPL |
- We saw how to use
CancellationToken
to allow the user to notify the delegate running in another thread that a cancellation is required. - We used
CancellationTokenSource
as means to create a token and to modify its state, so that this privilage is reserved to the caller of the task. - We understood that cancallation is a negotiation between the task caller and the task method, where the caller can request cancallation and the method may stop work and cancel the task.
- We understood that the caller cannot force the task to be cancelled - only to request it.
- We saw that in order for the delegate to cancel the task, in needs to throw
OperationCancelledException
or to use the token methods to do that.
- We understood that by rules of proper decoupling, the task delegate should not directly update the UI when progress is made
- We understood also that the task delegate cannot even get an
Action<T>
instance to report progress, because it does not know (and should not know) in which thread to execute it. - We used the
IProgress<T>
interface to pass an object that can be used to report progess - We understood that
Progress<T>
is a wrapper aroundAction<T>
that captures the synchronization context in which it was created and runs the delegate in that context. - We saw how to make the background delegate use the IProgress interface to report progress and how the UI uses it to update the progress bar.
- We saw how to convert our algorithm to LINQ
- We then saw how to easily convert it to Parallel LINQ by using the
AsParallel
method that converts to theIEnmuerable
toParallelQuery
- We saw how to support cancellation using parallel LINQ method:
WithCancellation
- We did not see it, but we can also report progress as described in the following article from Stack Overflow
- The final project contains also a demo of progress reporting using PLINQ
- We can get tasks to run in parallel by first creating the task and only then awaiting them.
- We used
Task.WhenAll
to combine a collection of tasks into a single task that completes when all the tasks in the collection complete and returns a collection of results. - We saw that if some or all of the tasks in the collection throw exceptions, the
WhenAll
task throws anAggregateException
with all the exceptions that were thrown in the original exceptions - We used
Task.WhenAny
to combine a collection of tasks into a single task that completes when one of the tasks in the collection completes. - The combined task returns - not the result of the task that completed - but the task itself.
- We saw that if an exception is thrown in some of the tasks in the collection, the
Task.WhenAny
does not throw it too. It returns the task that succeeded but does not pass the exceptions that were thrown in the others. - In order to catch these exceptions, and make sure that there are no unharvested exceptions, it is recommended to await the other tasks as well.
- I emphasized again, that it is extremely important to harvest the exceptions from the tasks, even if we do not intend to handle them, becuase when the garbage collector clears a task object, that contains an exception that was not thrown, it throws it and may crash the application.
- Tasks created with
TaskFactory.StartNew
are tasks that report completion of delegates, but not all tasks do that. - In fact, it is very important to remember that tasks do not run code at all. They just report completion and result of something... which could be anything, not just delegates
- We saw that
Task.Delay
creates a task that does not run code but ends after a specific delay- I emphasized that it does not create a new thread and sleeps in that thread, there is not extra thread from this method. It runs nothing, and ends upon timer event
- We saw that it also accepts cancellation token
- We saw that
Task.FromResult
creates a task that is already completed from a known result - We saw that we can also create tasks in other statuses, using
Task.FromException
andTask.FromCancelled
- We saw how to use
Task.FromResult
to implement caching
- We saw that
Task
is a read only object. You can read the status, the result, or the exception, but you can not set them - We saw that in order to create a task that we can control, we use an object called
TaskCompletionSource
- We used
TaskCompletionSource
to create a task that ends when the user presses a button - We made sure that the method that generates this task ends instantly, to free the main thread, so that the user may interact with the UI
- We saw how to also use the
CancellationToken
and register to the cancellation, so that we cancel the task if the cancellation is requsted.