What is a proper implementation of the IAsyncResult interface?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
IAsyncResult belongs to the old .NET Asynchronous Programming Model, usually called APM or the Begin/End pattern. A proper implementation must expose completion state consistently, signal waiters correctly, invoke callbacks exactly once, and pair cleanly with a matching End method, but for new code you should strongly prefer Task and async APIs instead.
When You Should Still Care
Most modern .NET code should not invent new IAsyncResult implementations. The main valid reason is interoperability with an older API surface that requires methods such as:
- '
BeginRead' - '
EndRead' - '
BeginInvoke' - '
EndInvoke'
If you are not integrating with that older contract, Task is the better design.
The Required Members
IAsyncResult requires:
- '
AsyncState' - '
AsyncWaitHandle' - '
CompletedSynchronously' - '
IsCompleted'
A minimal implementation also needs internal result storage, exception storage, callback dispatch, and a way to signal completion.
A Minimal Example
This is not meant to replace modern Task, but it shows the shape of a correct APM result object.
Pair It with Begin and End Methods
An IAsyncResult implementation only makes sense when the surrounding API follows the Begin/End pattern.
EndSquare is where callers block if needed, retrieve the result, and observe the stored exception.
CompletedSynchronously Must Be Honest
This property is not a performance hint you can fake. It tells the caller whether completion happened before the Begin method returned. If the operation actually finished later on a thread-pool thread, it must be false.
Incorrect values here can break callback logic in consumers that optimize for synchronous completion.
Dispose and Lifetime Concerns
If you expose a wait handle, you also need a consistent ownership story. In many implementations the End method is where the wait handle is observed and cleaned up. Forgetting that detail leads to leaked kernel handles.
That is one reason custom APM code is easy to get wrong.
Use Task for New Code
Modern equivalent:
This is shorter, safer, and much easier to compose than a custom IAsyncResult type.
Common Pitfalls
The biggest mistake is implementing IAsyncResult for new APIs when Task would be simpler and safer.
Another issue is forgetting that the Begin/End pair is the real contract. An IAsyncResult object by itself is not enough.
A third problem is setting CompletedSynchronously incorrectly or failing to signal the wait handle before invoking the callback.
Summary
- A proper
IAsyncResultimplementation must track state, completion, wait signaling, and exceptions consistently. - It should be paired with matching Begin and End methods.
- '
CompletedSynchronouslymust reflect reality, not guesswork.' - Resource cleanup matters because
AsyncWaitHandlehas lifetime costs. - For new code, prefer
Taskandasyncinstead of creating custom APM infrastructure.
Related reading
- What is a proper way to create awaitable function
- What is a race condition?
- What is a race condition?
- What is a replacement method for Task.Run in .NET 4.0 using C?
- What is a quick way to force CRLF in C / .NET?
- What is a singleton in C?
- What is a semaphore?
- What is a SIMPLE implementation of async.series?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.