What's the difference between Foo.Result and Task.Run Foo.Result in C?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
In C#, asynchronous programming comes with several patterns and methods for executing tasks. Two such methods are directly invoking the `.Result` property of a `Task` and using `Task.Run()` followed by accessing `.Result`. While both may seem similar, there are nuanced differences between using `Foo().Result` and `Task.Run(() => Foo()).Result`, which can have significant implications depending on the use case.
Understanding `Foo().Result`
When you have an async method `Foo()`, calling `Foo().Result` runs the method and waits for it to complete by blocking the calling thread until the `Task` is finished. The `.Result` property exposes the outcome of the task upon completion.
Example:
- Blocking Behavior: It's important to note that `.Result` can lead to thread blocking. If `FooAsync` involves synchronous blocking, it could risk a deadlock, especially on contexts like UI threads.
- Deadlock Situations: Commonly causes deadlocks in UI threads due to the synchronization context attempting to marshal back to the UI thread, which is blocked waiting for `Result`.
- Exception Handling: Exceptions thrown in the asynchronous operation are wrapped in an `AggregateException`.
- ThreadPool Execution: `Task.Run()` dispatches the work to the ThreadPool, potentially bypassing deadlock scenarios often seen with UI threads.
- Still Blocking: Despite mitigating deadlocks, it still blocks until the task completes, which may not be ideal in responsive applications.
- More Overhead: There is additional overhead associated with starting new tasks on the ThreadPool.
- Exception Handling: Similar to `Foo().Result`, exceptions are wrapped in an `AggregateException`.
- Asynchronous Contexts: For modern applications, it's recommended to use `await` instead of `.Result` to harness true asynchronous behavior, eliminating blocking and enhancing responsiveness.
- Avoiding Blocking: Consider refactoring synchronous calls in async methods to asynchronous variants wherever possible.
- UI Applications: Avoid using `.Result` or `.Wait()` within UI event handlers or main UI threads. Instead, refactor to make full use of `async` and `await`.
- Exception Handling Nuances: Always unwrap `AggregateException` and inspect `InnerExceptions` to handle exceptions appropriately.
Related reading
- What's the difference between Invoke and BeginInvoke
- What's the difference between Invoke and BeginInvoke
- What's the difference between static and dynamic schedule in OpenMP?
- What's the difference between SubscribeOn and ObserveOn
- What's the difference between groups and captures in .NET regular expressions?
- What's the difference between IEquatable and just overriding Object.Equals?
- What's the difference between Thread start and Runnable run
- What's the difference between Thread start and Runnable run

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseInterview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.