0% found this document useful (0 votes)
6 views61 pages

Using The Task Parallel Library For Asynchronous Programming Slides

The document provides an overview of using the Task Parallel Library for asynchronous programming, detailing how to run tasks, handle exceptions, and manage task continuations. It explains the difference between generic and non-generic tasks, as well as the importance of cancellation tokens and task status. Additionally, it emphasizes the benefits of using async and await for better readability and maintainability in asynchronous code.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views61 pages

Using The Task Parallel Library For Asynchronous Programming Slides

The document provides an overview of using the Task Parallel Library for asynchronous programming, detailing how to run tasks, handle exceptions, and manage task continuations. It explains the difference between generic and non-generic tasks, as well as the importance of cancellation tokens and task status. Additionally, it emphasizes the benefits of using async and await for better readability and maintainability in asynchronous code.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Using the Task Parallel Library for

Asynchronous Programming

Filip Ekberg
Principal Consultant & CEO

@fekberg [Link]
Introducing the Task

[Link](() => {

// Heavy operation to run somewhere else

});
Using Tasks without async & await

Obtain the result

Capture exceptions

Running continuations depending on success or failure

Cancelling an asynchronous operation


Read File Content Asynchronously

using var stream =


new StreamReader([Link]("file")));

var fileContent = await [Link]();


Using the Task

var response = await [Link](URL);

Returns a Task

Result of Awaits the Task


the operation
Task from the Task Parallel Library
Represents a single asynchronous operation
Functionality Provided by the Task

Execute work on a different thread

Get the result from the asynchronous operation

Subscribe to when the operation is done by introducing a


continuation

It can tell you if there was an exception


Introducing the Task

[Link](() => { /* Heavy operation */ });

[Link](SomeMetodMethod);
Introducing the Task

Queue this anonymous method


on the thread pool for execution

[Link](() => { /* Heavy operation */ });

[Link](SomeMetodMethod);

Queue this method


on the thread pool for execution
Generic vs Non-Generic [Link]

Task<T> task = [Link]<T>(() => {


return new T();
});

Task task = [Link](() => { });


Generic vs Non-Generic [Link]

Task<T> task = [Link]<T>(() => {


return new T(); An asynchronous operation
}); that returns a value

Task task = [Link](() => { });


Generic vs Non-Generic [Link]

Don’t need to explicitly


use [Link]<T>()

Task<T> task = [Link](() => {


return new T();
});

Task task = [Link](() => { });


Avoid queuing
heavy work back
on the UI thread
Obtaining the Result of a Task
Introduce a Continuation

var task = [Link](() => { });

var continuationTask =
[Link]((theTaskThatCompleted) => {

// This is the continuation


// which will run when “task” has finished

});
Introduce a Continuation

var task = [Link](() => { });

var continuationTask =
[Link]((theTaskThatCompleted) => {

// This is the continuation


// which will run when This
“task” has finished
continuation will NOT
execute on the original thread
});
Introduce a Continuation

var task = [Link](() => { });

These two are the same!

[Link]((theTaskThatCompleted) => {

// This is the continuation

});
Multiple Continuations

var task = [Link](() => { });

[Link]((t) => { /* Continuation 1 */ });


[Link]((t) => { /* Continuation 2 */ });
[Link]((t) => { /* Continuation 3 */ });
[Link]((t) => { /* Continuation 4 */ });
[Link]((t) => { /* Continuation 5 */ });
async & await is a much more
readable and maintainable
approach
Continuation Differences

[Link](_ => {
// This continuation executes asynchronously
// on a different thread
});

await task;
// This continuation executes on the original context
async & await may be
unnecessary in certain
situations
Demo

Demo: Nested asynchronous operations


Asynchronous Anonymous Methods

// Thread 1

[Link](async () => {
// Thread 2

await [Link](() => {


// Thread 3
});

// Thread 2
});

// Thread 1
Asynchronous anonymous
methods are NOT the same
as async void
Next: Handling Task Success and Failure
Handling Task Success and Failure
Continuing After an Exception

var loadLinesTask = [Link](() => {


throw new FileNotFoundException();
});

[Link]((completedTask) => {

// Running this may be unnecessary


// if you expect [Link]!
});
ContinueWith executes when
the Task completes no
matter if it’s successful,
faulted or cancelled
The Continuation Did Not Fail

[Link](() => {

throw new FileNotFoundException();


Faulted with attached exception!
})
.ContinueWith((completedTask) => {

})
.ContinueWith((completedContinuationTask) => {

}) Not faulted!
OnlyOnRanToCompletion

Task has no exceptions Task was not cancelled


await it will not throw an
aggregate exception
Always Validate Your Tasks

You can use async & await You can chain a continuation
using ContinueWith
TaskContinuationOptions
Specifies the behavior for a task that is created by using the ContinueWith
Continuing After an Exception

var loadLinesTask = [Link](() => {


throw new FileNotFoundException();
});

[Link]((completedTask) => {
// will always run
});

[Link]((completedTask) => {
// will not run if completedTask is faulted
}, [Link]);
Always validate your
asynchronous operations
Handling Exceptions

try
{
await task;
}
catch(Exception ex)
{
// log [Link]
}

[Link]((t) => {
// log [Link]
}, [Link]);
Next: Cancellation and Stopping a Task
Cancellation and Stopping a Task
Don’t force a user to wait for
a result they know is
incorrect.

Allow them to cancel!


CancellationTokenSource
Signals to a CancellationToken that it should be canceled.

Always call Dispose() on the cancellation token source after the


asynchronous operation completed
Cancellation Token Source

CancellationTokenSource cancellationTokenSource;

[Link]();

[Link](5000);
Cancellation Token Source

CancellationTokenSource cancellationTokenSource;

[Link]();
[Link]();

Signals to a Cancellation Token


that it should cancel
[Link](5000);
Cancellation Token Source

CancellationTokenSource cancellationTokenSource;

[Link]();
[Link](5000);

...
[Link](); Schedules a cancellation that
occurs after 5 seconds
Cancellation Token

CancellationTokenSource cancellationTokenSource;
CancellationToken token = [Link];

[Link](() => {}, token);

[Link](() => {

if([Link]) {}

});
Cancellation Token

CancellationTokenSource cancellationTokenSource;
CancellationToken token = [Link];

[Link](() => {}, token);

[Link](() => {

if([Link]) {}

});
Calling Cancel will not
automatically terminate the
asynchronous operaiton
Cancellation

CancellationTokenSource cancellationTokenSource;
CancellationToken token = [Link];

[Link]();
Will not start if Cancellation
Token is marked as Cancelled
[Link](() => {}, token);
Cancellation Token and
ContinueWith

CancellationTokenSource cancellationTokenSource;
CancellationToken token = [Link];

var task = [Link](() => {}, token);


[Link]((t) => {}, token);
Task Status

var token = new CancellationToken(canceled: true);

var task = [Link](() => "Won’t even start", token);

[Link]((completingTask) => {
// [Link] = Canceled
});
[Link]((completingTask2) => {
// [Link] = Canceled
});
Task Status

var token = new CancellationToken(canceled: true);

var task = [Link](() => "Won’t even start", token);

[Link]((completingTask) => {
// [Link] = Canceled
})
.ContinueWith((continuationTask) => {
// [Link] = RanToCompletion
});
Demo

Example: Cancellation with HttpClient


Every library could handle
cancellations differently
Task Parallel Library
async Task Process(CancellationToken token)
{
var task = [Link](() => {

// Perform an expensive operation

return ... ;

}, token);

var result = await task;

// Use the result of the operation


}
ContinueWith

var task = [Link](() => {

return ... ;

});

[Link]((completedTask) => {

// Continue..

});
ContinueWith

var task = [Link](() => {

return ... ;

});

[Link]((completedTask) => {

// Continue.. Asynchronous operation


executed on a different thread
});
Cross-Thread Communication

var task = [Link](() => {

return ... ;

});

[Link]((completedTask) => {

[Link](() => { /* Run me on the UI */ });

});
Be careful!

What happens if the method


you point to forces itself onto
the UI/calling thread?
Introducing Asynchronous Methods

Implement two versions of the Do not wrap the synchronous


method if you need both an method in a [Link] just to make
asynchronous and synchronous the code asynchronous. Copy the
versioon code to the asynchronous method
and implement it properly
Task Continuation Options

var task = [Link](() => {


throw new FileNotFoundException();
});

[Link]((completedTask) => {

// will not run if completedTask is faulted

}, [Link]);
Introducing a Task with [Link] to run
work on a different thread
Summary Obtaining the result and exceptions in the
continuation of a Task
Configure the continuation to only run on
success, failure or a cancellation
How to combine async and await with your
own asynchronous operations
Understand the difference between await
and ContinueWith
Next: Exploring Useful Methods in the
Task Parallel Library

You might also like