@@ -181,7 +181,7 @@ T PeformActionAndResetPosition(Stream s, long position)
181181 return action ( memoryStream ) ;
182182 }
183183
184- internal static async Task < T > WithSeekableMemoryStreamAsync < T > (
184+ internal static Task < T > WithSeekableMemoryStreamAsync < T > (
185185 DecoderOptions options ,
186186 Stream stream ,
187187 Func < Stream , CancellationToken , T > action ,
@@ -195,20 +195,31 @@ internal static async Task<T> WithSeekableMemoryStreamAsync<T>(
195195 throw new NotSupportedException ( "Cannot read from the stream." ) ;
196196 }
197197
198- T PeformActionAndResetPosition ( Stream s , long position , CancellationToken ct )
198+ Task < T > PeformActionAndResetPosition ( Stream s , long position , CancellationToken ct )
199199 {
200- T result = action ( s , ct ) ;
201-
202- // Issue #2259. Our buffered reads may have left the stream in an incorrect non-zero position.
203- // Reset the position of the seekable stream if we did not read to the end to allow additional reads.
204- // We check here that the input stream is seekable because it is not guaranteed to be so since
205- // we always copy input streams of unknown type.
206- if ( stream . CanSeek && stream . Position != s . Position && s . Position != s . Length )
200+ try
207201 {
208- stream . Position = position + s . Position ;
202+ T result = action ( s , ct ) ;
203+
204+ // Issue #2259. Our buffered reads may have left the stream in an incorrect non-zero position.
205+ // Reset the position of the seekable stream if we did not read to the end to allow additional reads.
206+ // We check here that the input stream is seekable because it is not guaranteed to be so since
207+ // we always copy input streams of unknown type.
208+ if ( stream . CanSeek && stream . Position != s . Position && s . Position != s . Length )
209+ {
210+ stream . Position = position + s . Position ;
211+ }
212+
213+ return Task . FromResult ( result ) ;
214+ }
215+ catch ( OperationCanceledException )
216+ {
217+ return Task . FromCanceled < T > ( cancellationToken ) ;
218+ }
219+ catch ( Exception ex )
220+ {
221+ return Task . FromException < T > ( ex ) ;
209222 }
210-
211- return result ;
212223 }
213224
214225 // NOTE: We are explicitly not executing the action against the stream here as we do in WithSeekableStream() because that
@@ -224,11 +235,20 @@ T PeformActionAndResetPosition(Stream s, long position, CancellationToken ct)
224235 return PeformActionAndResetPosition ( cms , cms . Position , cancellationToken ) ;
225236 }
226237
238+ return CopyToMemoryStreamAndActionAsync ( options , stream , PeformActionAndResetPosition , cancellationToken ) ;
239+ }
240+
241+ private static async Task < T > CopyToMemoryStreamAndActionAsync < T > (
242+ DecoderOptions options ,
243+ Stream stream ,
244+ Func < Stream , long , CancellationToken , Task < T > > action ,
245+ CancellationToken cancellationToken )
246+ {
227247 long position = stream . CanSeek ? stream . Position : 0 ;
228248 Configuration configuration = options . Configuration ;
229249 using ChunkedMemoryStream memoryStream = new ( configuration . MemoryAllocator ) ;
230250 await stream . CopyToAsync ( memoryStream , configuration . StreamProcessingBufferSize , cancellationToken ) . ConfigureAwait ( false ) ;
231251 memoryStream . Position = 0 ;
232- return PeformActionAndResetPosition ( memoryStream , position , cancellationToken ) ;
252+ return await action ( memoryStream , position , cancellationToken ) . ConfigureAwait ( false ) ;
233253 }
234254}
0 commit comments