@@ -62,9 +62,32 @@ private async IAsyncEnumerable<TOutput> ExecuteWithoutOrderPreservationAsync(Can
6262 // Complete output when all processing is done
6363 var completionTask = Task . Run ( async ( ) =>
6464 {
65- await producerTask . ConfigureAwait ( false ) ;
66- await Task . WhenAll ( consumerTasks ) . ConfigureAwait ( false ) ;
67- outputChannel . Writer . Complete ( ) ;
65+ Exception ? exception = null ;
66+ try
67+ {
68+ await producerTask . ConfigureAwait ( false ) ;
69+ await Task . WhenAll ( consumerTasks ) . ConfigureAwait ( false ) ;
70+ }
71+ catch ( Exception ex )
72+ {
73+ exception = ex ;
74+ }
75+ finally
76+ {
77+ if ( exception != null )
78+ {
79+ outputChannel . Writer . TryComplete ( exception ) ;
80+ }
81+ else
82+ {
83+ outputChannel . Writer . TryComplete ( ) ;
84+ }
85+ }
86+
87+ if ( exception != null )
88+ {
89+ throw exception ;
90+ }
6891 } , cancellationToken ) ;
6992
7093 // Yield results as they complete
@@ -138,7 +161,36 @@ private async IAsyncEnumerable<TOutput> ExecuteWithOrderPreservationAsync(Cancel
138161 await Task . Delay ( 10 , cancellationToken ) . ConfigureAwait ( false ) ;
139162 }
140163 }
141- outputChannel . Writer . Complete ( ) ;
164+ } , cancellationToken ) ;
165+
166+ // Ensure channel completion when all tasks finish
167+ var channelCompletionTask = Task . Run ( async ( ) =>
168+ {
169+ Exception ? exception = null ;
170+ try
171+ {
172+ await yieldingTask . ConfigureAwait ( false ) ;
173+ }
174+ catch ( Exception ex )
175+ {
176+ exception = ex ;
177+ }
178+ finally
179+ {
180+ if ( exception != null )
181+ {
182+ outputChannel . Writer . TryComplete ( exception ) ;
183+ }
184+ else
185+ {
186+ outputChannel . Writer . TryComplete ( ) ;
187+ }
188+ }
189+
190+ if ( exception != null )
191+ {
192+ throw exception ;
193+ }
142194 } , cancellationToken ) ;
143195
144196 // Yield from output channel
@@ -160,21 +212,30 @@ private async Task ProcessOrderedItemAsync(
160212 SemaphoreSlim semaphore ,
161213 CancellationToken cancellationToken )
162214 {
215+ var tcs = new TaskCompletionSource < TOutput > ( ) ;
216+
217+ await orderingLock . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
218+ try
219+ {
220+ orderingDictionary [ index ] = tcs ;
221+ }
222+ finally
223+ {
224+ orderingLock . Release ( ) ;
225+ }
226+
163227 try
164228 {
165229 var result = await _taskSelector ( item ) . ConfigureAwait ( false ) ;
166-
167- await orderingLock . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
168- try
169- {
170- var tcs = new TaskCompletionSource < TOutput > ( ) ;
171- tcs . SetResult ( result ) ;
172- orderingDictionary [ index ] = tcs ;
173- }
174- finally
175- {
176- orderingLock . Release ( ) ;
177- }
230+ tcs . TrySetResult ( result ) ;
231+ }
232+ catch ( OperationCanceledException )
233+ {
234+ tcs . TrySetCanceled ( ) ;
235+ }
236+ catch ( Exception ex )
237+ {
238+ tcs . TrySetException ( ex ) ;
178239 }
179240 finally
180241 {
0 commit comments