You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/csharp/asynchronous-programming/async-scenarios.md
+65Lines changed: 65 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -167,6 +167,71 @@ If your program needs the result of a task, write code that implements the `awai
167
167
|_Continue when **all** tasks complete_|`Task.WaitAll`|`await Task.WhenAll`|
168
168
|_Continue after some amount of time_|`Thread.Sleep`|`await Task.Delay`|
169
169
170
+
### Synchronous access to asynchronous operations
171
+
172
+
In rare scenarios, you might need to block on asynchronous operations when the `await` keyword isn't available throughout your call stack. This situation commonly occurs in legacy codebases or when integrating asynchronous methods into synchronous APIs that can't be changed.
173
+
174
+
> [!WARNING]
175
+
> Synchronous blocking on asynchronous operations can lead to deadlocks and should be avoided whenever possible. The preferred solution is to use `async`/`await` throughout your call stack.
176
+
177
+
When you must block synchronously on a `Task`, here are the available approaches, listed from most to least preferred:
178
+
179
+
#### Use GetAwaiter().GetResult()
180
+
181
+
The `GetAwaiter().GetResult()` pattern is generally the preferred approach when you must block synchronously:
182
+
183
+
```csharp
184
+
// When you cannot use await
185
+
Task<string>task=GetDataAsync();
186
+
stringresult=task.GetAwaiter().GetResult();
187
+
```
188
+
189
+
This approach:
190
+
191
+
- Preserves the original exception without wrapping it in an `AggregateException`
192
+
- Blocks the current thread until the task completes
193
+
- Still carries deadlock risk if not used carefully
194
+
195
+
#### Use Task.Run for complex scenarios
196
+
197
+
For complex scenarios where you need to isolate the asynchronous work:
198
+
199
+
```csharp
200
+
// Offload to thread pool to avoid context deadlocks
-**Exception handling**: Test error scenarios carefully as exception behavior differs between patterns
232
+
233
+
For more detailed guidance on the challenges and considerations of synchronous wrappers for asynchronous methods, see [Should I expose synchronous wrappers for asynchronous methods?](https://devblogs.microsoft.com/pfxteam/should-i-expose-synchronous-wrappers-for-asynchronous-methods/).
234
+
170
235
### Consider using ValueTask type
171
236
172
237
When an asynchronous method returns a `Task` object, performance bottlenecks might be introduced in certain paths. Because `Task` is a reference type, a `Task` object is allocated from the heap. If a method declared with the `async` modifier returns a cached result or completes synchronously, the extra allocations can accrue significant time costs in performance critical sections of code. This scenario can become costly when the allocations occur in tight loops. For more information, see [generalized async return types](../language-reference/keywords/async.md#return-types).
0 commit comments