Download Understanding Tasks & Async Methods in C#: Cancellation, Exceptions, Composition and more Slides Human Resource Management in PDF only on Docsity!
Task cancellation
• One cannot "kill", "stop" or "suspend" a task
• But one can request cancellation, and the
task can check for and acknowledge (or not)
31
public static void ComputeTask(CancellationToken token) { for (int i=0; i<100000000; i++) token.ThrowIfCancellationRequested(); }
CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken token = cts.Token; Task task = Task.Run(() => ComputeTask(token), token);
cts.Cancel(); // task.Wait();
Check and
acknowledge
Running Canceled Would throw AggregateException containing TaskCanceledException
Exceptions in tasks
• An exception exn thrown by a task is not
propagated to the task's creator
• Instead
– the task is moved to state Faulted
– t.Wait() and t.Result will throw an
AggregateException containing exn
– WaitAll collects thrown exceptions from subtasks
32
Asynchronous methods (C# 4.5)
• Tasks allow compositional asynchrony
• But using ContinueWith gets rather hairy
• C# 4.5 has asynchronous methods
– Declared using async keyword
– Must return Task or Task or void
– May contain await e where e is a task
– The rest of the method is the continuation of e
• Implementation of asynchronous method:
– the compiler rewrites it to a state machine
– much like yield return in iterator methods
34
static async Task NcbiEntrezAsync(String query) { byte[] bytes = await new WebClient().DownloadDataAsync(...)); return ASCIIEncoding.ASCII.GetString(bytes); }
Asynchronous web download
35
• Declare the method async
• Use await instead of ContinueWith(...)
• Use as before, or from other async methods:
static async Task NcbiProteinAsync(String id) { return await NcbiEntrezAsync("efetch.fcgi?...&id=" + id); }
static async Task<String[]> NcbiProteinParallelAsync(... ids) { var tasks = from id in ids select NcbiProteinAsync(id); return await Task.WhenAll(tasks); }
Composing asynchronous methods
• An NCBI PubMed query is done in two phases
– First do an esearch to get a WebKey in XML
– Then use efetch and the WebKey to get results
• To do this asynchronously using Task and
ContinueWith would be quite convoluted
• Rather easy with asynchronous methods:
37
static async Task NcbiPubmedAsync(String term) { String search = String.Format("esearch.fcgi?...", term); XmlDocument xml = new XmlDocument(); xml.LoadXml(await NcbiEntrezAsync(search)); XmlNode node = xml["eSearchResult"]; String fetch = String.Format("...&db=Pubmed&WebEnv={1}", ... node["WebEnv"].InnerText); return await NcbiEntrezAsync("efetch.fcgi?...&" + fetch); }
Composability, general timeout
• Async methods can be further composed, eg
– do all tasks asynchronously using WhenAll
– do some task asynchronously using WhenAny
– do task, subject to timeout
– etc
• A general timeout task combinator
38
static async Task Timeout(Task task, int ms, T alt) { if (task == await Task.WhenAny(task, Task.Delay(ms))) return task.Result; else return alt; }