A synchronous HTTP search waits for each request before continuing. In C#, async and await let the search use Tasks so multiple requests can be in progress at once. A Task represents work, but it does not necessarily run on a separate thread. section 4.4
Listing 4.34 Modifying GetComic to be asynchronous
public static async Task<Comic?> GetComicAsync( #1
int number, #2
CancellationToken cancellationToken) #3
{
if (cancellationToken.IsCancellationRequested) #4
{
return null;
}
try
{
var path = number == 0 ? "info.0.json"
: $"{number}/info.0.json";
var stream = await client.GetStreamAsync( #5
path, cancellationToken); #6
return await JsonSerializer.DeserializeAsync<Comic>( #7
stream, cancellationToken: cancellationToken); #6
}
catch (AggregateException e)
when (e.InnerException is HttpRequestException)
{
return null;
}
catch (HttpRequestException)
{
return null;
}
catch (TaskCanceledException) #8
{
return null;
}
}
GetComicAsync returns Task<Comic?> and awaits both the HTTP stream and JSON deserialization. It passes a CancellationToken to each operation and handles request failures and cancellation. section 4.4
Listing 4.35 Asynchronous version of GetComicWithTitle
static async Task<Comic?> GetComicWithTitleAsync( #1
string title)
{
var cancellationToken = new CancellationTokenSource(); #2
var lastComic = await Comic.GetComicAsync(0, #3
cancellationToken.Token);
var tasks = new List<Task>(); #4
Comic? foundComic = null; #5
for (int number = lastComic!.Number;
number > 0;
number--)
{
var localNumber = number; #6
var getComicTask = Comic.GetComicAsync(localNumber, #7
cancellationToken.Token);
var continuationTask = getComicTask.ContinueWith( #8
t => { #9
try
{
var comic = t.Result;
if (comic != null &&
string.Equals(title, comic!.Title,
StringComparison.OrdinalIgnoreCase))
{
cancellationToken.Cancel(); #10
foundComic = comic;
}
}
catch (TaskCanceledException) {} #11
});
tasks.Add(continuationTask); #12
}
await Task.WhenAll(tasks); #13
return foundComic;
}
The title search starts comic-fetch Tasks while iterating over comic numbers, then attaches continuations to inspect their results. section 4.4
The caller must also await the asynchronous search. Measure elapsed time with Stopwatch, but treat a slow server or throttling as a possible influence on the result. section 4.4
















