discovering dot net tasks
TRANSCRIPT
Discovering .NET Tasks !Vincent GrondinGeneral Manager – Solutions Vet a CDMV subsidiary
C# MVP
.NET Montreal User Group LeaderBlog: http://geekswithblogs.net/vincentgrondin
Before we dive into this…
• Who worked with Tasks before?
• Who worked with Task Parallel Library
before?
• Who worked with Async and Await before?
•DEMO-WARE !!!!
Disclaimer !
Disclaimer !
Disclaimer !
Disclaimer !
Content
• What are Tasks?
• When should you use Tasks?
• Various kind of Task relationships
• Exception handling in Tasks
• Cancellation handling in Tasks
What are Tasks?
• A task is an asynchronous unit of work
• A task is nothing more than a class that wraps a method
• Think of tasks as the evolution of Asynchronous Delegates
• Tasks offer greater control on :
– where should the method be executed (threading)
– what happens when the method has finished executing
– how to handle exceptions in asynchronous scenarios
– how to handle a cancellation in asynchronous scenarios
• They allow for a more « Functional » programming model by
clearly defining a unit of work.
– When this task ends, fails or is canceled, start this task
What are tasks?
• You can wait for a task to complete but it’s not a must!
• Task execute void returning methods. (Action)
• Task<TResult> execute methods that return TResult
– Example : You want to convert a method to a task…
• Suppose that your method returns a Bool
• The Task based equivalent of this method would be a Task<Bool>
• Wrap a task around your method
• Task<Bool> myTask = new Task(() =>
{
return this.MyBoolReturningMethod() ;
});
What are tasks?
• Waiting for a task means…
– the thread that calls “.Wait();” on the task is blocked
– the code execution in this method stops at the “.Wait();” line.
– when the task finishes, the next statement is right after the “.Wait();”.
• Awaiting a task means…
– the current thread is free to process other pieces of code
– the code execution in this method stops at the “await point”.
– the rest of the method after the “await point” is put into a “callback”
– the code resumes after the method call in the parent method
– when the task finishes, the next statement is right after the “await
point”
• …with await also comes other pains…
What are Tasks – Wait vs Await
What are Tasks? – Demo 1 & 2
What are Tasks? – Demo 3
Disclaimer !
When should you use Tasks?
When should you use Tasks?
• Any time you want to do something
asynchronously.
• When you need to communicate with a
service
When should you use Tasks? – Demo 4
Various kind of Task relationships
Why does the relationship type matters?
Parent-AttachedChild relationship
Parent-DetachedChild relationship
Antecedent-Continuation relationship
Why does the relationship type matters?
• Tasks can relate one to another and this relationship has
serious implications over the following :
– Should a Task wait for another to complete before joining back to the
calling thread?
– How will exceptions be propagated between tasks in a relationship?
– Will the status of a task affect the status of another task in a
relationship?
• It all depends on the TYPE of relationship used
Parent-AttachedChild relationship
• The parent Task starts another Task inside itself and
explicitly attaches it as its child.
• Use “TaskCreationOptions.AttachedToParent” when
creating the child Task.
• A parent Task can have many attached children
• The parent Task will wait for all children to complete (faulted-canceled-completed)
• Exceptions will be propagated from a child to its parent.
• The parent Task status depends on the status of it’s
children.
Parent-AttachedChild relationship
Task 1 (parent)
Task 2(child)
Task 3(child)
Task 4(child)
2
3
4
Main thread
1
Parent-DetachedChild relationship
• The parent Task starts another Task inside itself.
• A parent Task can have many detached and / or attached
children
• The parent Task won’t wait for detached children to
complete (faulted-canceled-completed)
• Exceptions won’t be propagated from a child to its parent.
• The parent Task status doesn’t depend on the status of its
children.
Parent-DetachedChild relationship
Task 1 (parent)
Task 2(child)
Task 3(child)
Task 4(child)
2
3
4
Main thread
1
Antecedent-Continuation relationship
• Happens when you define a Task using the “ContinueWith”
command on a Task.
– The first Task is the Antecedent
– The second Task is the Continuation and receives the Antecedent
Task as a parameter so it can use it in it’s own Task.
• Continuation Tasks won’t run until the parent and all it’s
attached children Tasks complete (faulted-canceled-completed)
• Exceptions won’t propagate to the Antecedent Task
• The status of the Continuation Task won’t affect the status of
the Antecedent Task
• Continuation Tasks are a great way to handle exceptions on
Antecedents Tasks!
• Chaining Tasks one after the other in a “Antecedent-
Continuation” relationship…
MainTask
Error Handling
Error Handling &
Continuation of the
workflow
Antecedent-Continuation relationship
• Another form of Antecedent-Continuation relationship is what I call a “Forked
Continuation” relationship
• Use the TaskContinuationOptions on your Continuation Task to specify which
Task to use when
MainTask
Error Handling
Continuation of the
workflow
Cancel
OnlyOnRanToCompletion
Antecedent-Continuation relationship
Antecedent-Continuation relationship – Demo 5
Disclaimer
• If you write a Task that has a Continuation Task attached to it, make sure you wait
for the right Task otherwise…. you’re in for surprises !
task.Wait()
Pitfalls
How to handle exceptions?
Facts about exceptions in Tasks
What’s the Observed Task concept?
Pitfalls
• A Task that throws an unhandled exception will add the exception to a list
of exceptions inside an AggregateException and throw this new
AggregateException.
• This is also true in a Parent-AttachedChild relationship. The
AggregateException can contain other AggregateExceptions!
• Use the AggregateException’s “Flatten” method to bring all these
recursive lists to a single list of exceptions.
Anyone an expert in nested “ForEach” or recursion here????
Facts about exceptions in Tasks
• Code inside a Task can be protected against unhandled exception like
standard .NET code using a Try-Catch block.
• “Ran to Completion” is the state for a Task that completed normally.
Check it’s IsCompleted property.
• “Faulted” is the state for a Task that completed with an
“AggregateException” thrown. Check it’s IsFaulted property.
• “Canceled” is the state for a Task that completed with a
“TaskCanceledException” thrown. Check it’s IsCanceled property.
Facts about exceptions in Tasks
• Exceptions in Tasks happen on the Task’s thread not on main thread
• Exceptions in Tasks under Framework 4 will crash your process unless
they are “Observed”.
• A Task’s exception is deemed “Observed” when…
– …the Task’s .Exception property is accessed
– …or you call Wait/WaitAll on the Task
– …or the Task’s Result is accessed.
• The CLR will raise the “UnobservedTaskException” event when an
“Unobserved” Task is FINALIZED (TaskScheduler.UnobservedTaskException +=…)
– You may need to force a GC.Collect to see the event being raised
• This will be your last chance to :
– log the exception that went unhandled
– prevent your process from crashing using the argument’s .SetObserved() method
What’s the Observed Task concept?
• Exceptions in Tasks under Framework 4.5 no longer crash your process
when they aren’t “Observed” ****** Go back to slide 28!.
• NOT considered a breaking change because the event is triggered.
• You can revert to .NET 4 behavior with a simple config file entry:
What’s the Observed Task concept?
Disclaimer !
• If you await a Task, everything changes and AggregateException
no longer get’s thrown, only the FIRST exception is thrown.
• The Task’s Exception property STILL CONTAINS the
AggregateException
Pitfall!
Disclaimer !
• What state will a Task be in if you catch an exception that
happen inside the Task and not let it bubble up?
– Completed !!!!
Pitfall!
Disclaimer !
• If you create an async void method like this
• …and let potential exceptions bubble up past the async void…
– The Task is deemed “unobserved”
– It will crash your process even under Framework 4.5.
Pitfall!
How to handle exceptions? – Demo 6
Cancellation handling in Tasks
Basics
Cancelling a Task you define
Cancelling a Task you didn’t define
Handling the cancellation
• What does cancelling execution implies?
– You have a logical operation with a “start” and “end” point
– You want to abruptly terminate this operation before the planned “end” point
– You want to skip all code between “now” and the “end” point and resume right after the
“end” point.
– You do not care what state your operation will be in when you cancel it
– You want to know that the operation was cancelled
• With that in mind, what’s the best way to achieve this?
– Exception !
• Cancellation in Tasks are handled via the following concepts:
– OperationCanceledException or TaskCanceledException
– CancellationTokenSource
– CancellationToken
– CancellationToken.ThrowIfCancellationRequested or CancellationTokenSource.Cancel
– Try-Catch
Basics
• If you define a Task (Run, StartNew, Start) and wish to build it
cancellable, you must declare a CancellationTokenSource
• You cancel the Task by calling .Cancel() then call
ThrowIfCancellationRequested on the CancellationSource’s Token.
Cancelling a Task you define
• You are responsible for checking the
CancellationToken regularly inside your
Task.
Cancelling a Task you define
• Most of the methods to define a Task offer an overload that accepts a
CancellationToken
• This means 2 things:
– Token is “associated” with the Task
– Token checked once before Tasks starts
Cancelling a Task you define
• When you do not define the Task and simply use a method that returns
a Task and accepts a CancellationToken like this:
• …the Token is “Associated” with the Task like previously
• Obviously means you have no access to the body of the Task and the
Task is responsible for checking for cancellation.
Cancelling a Task you didn’t define
• Try-Catch… but catch which exception type?
• The right way of canceling a Task is to use
ThrowIfCancellationRequested which will throw an
OperationCanceledException.
• Catch this exception when inside the Task…
Handling the cancellation
Disclaimer !
OperationCanceledException
AggregateException
TaskCanceledException
Handling the cancellation
• A method that accepts a CancellationToken will throw an
OperationCanceledException… Take a look at “Task.Wait()”
• Back to our previous example…
• There is a big difference between canceling a Task and canceling the wait on a
Task
• Why not always catch both AggregateException and
OperationCanceledException and comment the reason why?
Token inside vs outside a Task
• Do not dive into Tasks without proper readings
– Exception Handling
– Cancellation
– Async - Await
– Task Parallel Library
• http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx
• http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx
• http://msdn.microsoft.com/en-us/library/jj155759.aspx
Take away!
Thank You For Attending!!!Vincent GrondinGeneral Manager – Solutions Vet a CDMV subsidiary
C# MVP
.NET Montreal User Group LeaderBlog: http://geekswithblogs.net/vincentgrondin