Pass parameters to WebClient.DownloadFileCompleted event
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
In older .NET code that still uses WebClient, DownloadFileCompleted is an event callback, so the handler often needs some context about which download just finished. The standard way to pass that context is the userToken argument on DownloadFileAsync, which later appears as e.UserState in the completion event.
That is much safer than storing per-download state in global variables or shared fields. It also scales correctly when several downloads are running at the same time.
Use the userToken Overload
DownloadFileAsync has an overload that accepts a third argument for caller-provided state:
This is the intended pattern for attaching request-specific data to the later completion event.
Why UserState Matters for Multiple Downloads
If several downloads happen concurrently, the completion handler needs a reliable way to distinguish them. Using a token object per request solves that:
Each completion callback receives the matching context through e.UserState. That avoids race conditions that appear when all downloads share the same mutable field.
Check Success, Failure, and Cancellation Separately
Do not treat DownloadFileCompleted as automatic success. The event fires for completion, failure, and cancellation, so the handler should check:
- '
e.Cancelled' - '
e.Error' - success only if both are absent
That is especially important in legacy event-driven code, where it is easy to log "done" without checking the actual outcome.
A Small Helper Pattern
If the codebase still uses several WebClient downloads, a small wrapper can make the event pattern less repetitive:
That keeps the context creation and event-state pattern consistent across call sites.
WebClient Is Legacy
For new code, HttpClient with task-based async APIs is usually a better choice. It is easier to compose, test, and cancel cleanly:
Still, when you are maintaining an existing event-based codebase, userToken plus e.UserState is the right pattern for passing parameters into DownloadFileCompleted.
Common Pitfalls
The biggest mistake is storing per-download context in shared fields instead of passing it through userToken. That falls apart as soon as multiple downloads overlap.
Another common issue is ignoring e.Error and e.Cancelled and assuming that the completion event means success.
Developers also sometimes cast e.UserState without checking for null or the wrong type. If different callers reuse the same handler, be defensive.
Finally, mixing old event-driven WebClient code with newer async patterns without a plan can make the codebase harder to follow. If migration is underway, isolate legacy downloads behind a small adapter.
Summary
- Pass request-specific parameters through the
userTokenoverload ofDownloadFileAsync. - Read the token back from
e.UserStateinsideDownloadFileCompleted. - Use a separate context object for each concurrent download.
- Check cancellation and error states explicitly before treating a download as successful.
- Prefer
HttpClientfor new development, but useUserStatecorrectly in legacyWebClientcode.
Related reading
- Passing a method parameter using Task.Factory.StartNew
- Passing a single item as IEnumerableT
- Passing arguments to C generic new of templated type
- Passing data to Master Page in ASP.NET MVC
- Passing Moq mock-objects to constructor
- Path to MSBuild
- Path.Combine absolute with relative path strings
- Path.Combine and the dot notation

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.