I skipped last week’s blog post (since I was working on the site redesign), so today is a 2-for-1 deal! :)
AsyncState property implements
IAsyncResult.AsyncState. This member was useful back in the day, but not so much in modern applications.
When asynchronous programming was going through its awkward teen stage,
AsyncState was an important part of the Asynchronous Programming Model (APM). The
Begin* method would take a
state parameter, which is assigned to the
IAsyncResult.AsyncState member. Later, when the application code’s callback is invoked, it could access the
AsyncState value to determine which asynchronous operation completed.
IAsyncResult.AsyncState (and other “state”-like parameters) are no longer necessary these days; a lambda callback can easily capture any number of local variables in a type-safe way. I prefer the lambda approach; it is more expressive, less brittle, and more flexible than a single
object state parameter. However, the
state parameter approach avoids memory allocation, so it is still sometimes used in performance-sensitive code.
In modern code, the
Task.AsyncState member is mainly used for interoperation from
Task to APM. This is only necessary if you’re writing
await code that must exist within an older asynchronous framework (a rare situation these days). In that scenario, you’re implementing the
End* methods and using a
Task instance as your implementation of
IAsyncResult. The standard approach is to create a
TaskCompletionSource<T>, and you pass the
state parameter into the
There really isn’t a need to read
AsyncState in modern code; it’s mainly important just because it implements
CreationOptions merely allows you to read the task creation options that were used to create this task. You can specify these options when you create a task using the task constructor,
TaskCompletionSource<T>. I’ll cover the meanings of these options later, when we cover
However, there’s almost no reason to read the task creation options once the task has been created. This would only be necessary if you were doing some really funky work with parent/child tasks or task scheduling - far beyond the normal scenarios for asynchronous or parallel tasks.
Once again none of these members are actually useful in real-world code.