@@ -648,12 +648,12 @@ private static async Task<Task> ToParallelLoopImplementation(
648
648
}
649
649
650
650
// The only expected exception at this point is an OperationCanceledException,
651
- // originated from either the stoppingToken ot the cancelingToken.
651
+ // originated from either the stoppingToken or the cancelingToken.
652
652
var oce = ex as OperationCanceledException ;
653
653
if ( oce != null )
654
654
{
655
655
if ( oce . CancellationToken == cancelingToken )
656
- return Task . FromCanceled ( oce . CancellationToken ) ; // https://stackoverflow.com/questions/69552580/a-canceled-task-propagates-two-different-types-of-exceptions-depending-on-how-i
656
+ return TaskFromCanceledSafe ( oce . CancellationToken ) ; // https://stackoverflow.com/questions/69552580/a-canceled-task-propagates-two-different-types-of-exceptions-depending-on-how-i
657
657
658
658
if ( oce . CancellationToken == stoppingToken ) return Task . CompletedTask ;
659
659
}
@@ -683,12 +683,19 @@ private static Task<object> CreateTask(ParallelLoopEntry entry, object argument,
683
683
else // SyncAction & IsSynchronous
684
684
{
685
685
try { task = Task . FromResult ( entry . SyncAction ( argument ) ) ; }
686
- catch ( OperationCanceledException oce ) { task = Task . FromCanceled < object > ( oce . CancellationToken ) ; }
686
+ catch ( OperationCanceledException oce ) { task = TaskFromCanceledSafe ( oce . CancellationToken ) ; }
687
687
catch ( Exception ex ) { task = Task . FromException < object > ( ex ) ; }
688
688
}
689
689
return task ;
690
690
}
691
691
692
+ private static Task < object > TaskFromCanceledSafe ( CancellationToken token )
693
+ {
694
+ var tcs = new TaskCompletionSource < object > ( ) ;
695
+ tcs . TrySetCanceled ( token ) ;
696
+ return tcs . Task ;
697
+ }
698
+
692
699
private static Task < object > CanceledToFaultedConditional ( Task < object > task ,
693
700
CancellationToken stoppingToken , CancellationToken cancelingToken )
694
701
{
0 commit comments