@@ -21,6 +21,7 @@ internal static class TaskHelpersExtensions
2121 /// </summary>
2222 internal static Task Catch ( this Task task , Func < CatchInfo , CatchInfo . CatchResult > continuation , CancellationToken cancellationToken = default ( CancellationToken ) )
2323 {
24+ // Fast path for successful tasks, to prevent an extra TCS allocation
2425 if ( task . Status == TaskStatus . RanToCompletion )
2526 {
2627 return task ;
@@ -40,10 +41,12 @@ internal static class TaskHelpersExtensions
4041 /// </summary>
4142 internal static Task < TResult > Catch < TResult > ( this Task < TResult > task , Func < CatchInfo < TResult > , CatchInfo < TResult > . CatchResult > continuation , CancellationToken cancellationToken = default ( CancellationToken ) )
4243 {
44+ // Fast path for successful tasks, to prevent an extra TCS allocation
4345 if ( task . Status == TaskStatus . RanToCompletion )
4446 {
4547 return task ;
4648 }
49+
4750 return task . CatchImpl ( ( ) => continuation ( new CatchInfo < TResult > ( task ) ) . Task , cancellationToken ) ;
4851 }
4952
@@ -55,8 +58,6 @@ private static Task<TResult> CatchImpl<TResult>(this Task task, Func<Task<TResul
5558 // Stay on the same thread if we can
5659 if ( task . IsCompleted )
5760 {
58- Contract . Assert ( task . IsFaulted || task . IsCanceled ) ; // caller ensures
59-
6061 if ( task . IsFaulted )
6162 {
6263 try
@@ -80,8 +81,12 @@ private static Task<TResult> CatchImpl<TResult>(this Task task, Func<Task<TResul
8081 {
8182 return TaskHelpers . Canceled < TResult > ( ) ;
8283 }
83-
84- Contract . Assert ( task . Status != TaskStatus . RanToCompletion ) ;
84+ if ( task . Status == TaskStatus . RanToCompletion )
85+ {
86+ TaskCompletionSource < TResult > tcs = new TaskCompletionSource < TResult > ( ) ;
87+ tcs . TrySetFromTask ( task ) ;
88+ return tcs . Task ;
89+ }
8590 }
8691
8792 // Split into a continuation method so that we don't create a closure unnecessarily
@@ -242,7 +247,7 @@ internal static Task Finally(this Task task, Action continuation)
242247 {
243248 // Stay on the same thread if we can
244249 if ( task . IsCompleted )
245- {
250+ {
246251 try
247252 {
248253 continuation ( ) ;
@@ -251,7 +256,7 @@ internal static Task Finally(this Task task, Action continuation)
251256 catch ( Exception ex )
252257 {
253258 return TaskHelpers . FromError ( ex ) ;
254- }
259+ }
255260 }
256261
257262 // Split into a continuation method so that we don't create a closure unnecessarily
@@ -267,7 +272,7 @@ internal static Task<TResult> Finally<TResult>(this Task<TResult> task, Action c
267272 {
268273 // Stay on the same thread if we can
269274 if ( task . IsCompleted )
270- {
275+ {
271276 try
272277 {
273278 continuation ( ) ;
@@ -276,7 +281,7 @@ internal static Task<TResult> Finally<TResult>(this Task<TResult> task, Action c
276281 catch ( Exception ex )
277282 {
278283 return TaskHelpers . FromError < TResult > ( ex ) ;
279- }
284+ }
280285 }
281286
282287 // Split into a continuation method so that we don't create a closure unnecessarily
0 commit comments