Passing a method parameter using Task.Factory.StartNew
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
You can pass a method parameter to Task.Factory.StartNew either by capturing it in a lambda or by using the overload that accepts an object state value. Both work, but they are not equally readable or equally appropriate in modern .NET code.
The bigger point is that StartNew is not the default recommendation for simple asynchronous work anymore. In many cases, Task.Run is clearer unless you specifically need StartNew options or scheduler control.
The Most Readable Pattern: Use a Lambda
For straightforward parameter passing, a lambda is usually the cleanest approach.
The lambda closes over value, so the method receives the parameter naturally.
Use the State Overload When You Need It
StartNew also has an overload that accepts a state object.
This avoids creating a closure, but the downside is loss of type safety because the parameter arrives as object and usually requires a cast.
For most application code, the lambda version is easier to read and maintain.
Multiple Parameters
If the method takes several values, the lambda approach stays simple.
Trying to force multiple values through the single object state parameter usually makes the code less clear, not more.
Why Task.Run Is Often Better
If your only goal is to offload work to the thread pool, Task.Run is usually the more modern choice.
Task.Factory.StartNew exposes more options, but it also has more footguns around schedulers and async delegates. That is why many developers now use Task.Run for simple background work and reserve StartNew for advanced cases.
Be Careful with Async Delegates
One common trap is using StartNew with an async lambda and expecting it to behave like Task.Run.
Because StartNew with an async lambda produces a nested Task<Task>, you often need Unwrap(). This surprises many people. Task.Run handles this more naturally.
When StartNew Still Makes Sense
Task.Factory.StartNew still matters when you need:
- a custom task scheduler
- long-running task hints
- attached child-task behavior
- fine-grained creation options
If you do not need those features, prefer the simpler API.
Common Pitfalls
- Using the
object stateoverload everywhere and filling the code with fragile casts. - Reaching for
StartNewwhenTask.Runwould be simpler and clearer. - Forgetting that
StartNewwith anasyncdelegate returns a nested task. - Assuming parameter passing is the hard part when the real issue is task-scheduler behavior.
- Capturing mutable variables in closures without understanding when their values may change.
Summary
- The easiest way to pass parameters to
Task.Factory.StartNewis usually a lambda. - '
StartNewalso supports a state-object overload, but it is less type-safe.' - For multiple parameters, lambdas stay cleaner than packing values into
object. - '
Task.Runis often the better default for simple thread-pool work.' - Use
StartNewwhen you genuinely need its advanced scheduling or task-creation options.
Related reading
- Passing asynchronously acquired data to child props
- passing multiple arguments to promise resolution within setTimeout
- Passing object by reference to stdthread in C11
- passing parameters to Node.js async waterfall
- Passing a single item as IEnumerableT
- Passing arguments to C generic new of templated type
- Passing value into next Promises argument
- Pattern for updating slave SQL Server 2008 databases from a master whilst minimising disruption

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.