SkipWhile.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace System.Linq
  9. {
  10. public static partial class AsyncEnumerable
  11. {
  12. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
  13. {
  14. if (source == null)
  15. throw Error.ArgumentNull(nameof(source));
  16. if (predicate == null)
  17. throw Error.ArgumentNull(nameof(predicate));
  18. #if USE_ASYNC_ITERATOR
  19. return Create(Core);
  20. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  21. {
  22. var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false);
  23. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  24. {
  25. while (await e.MoveNextAsync())
  26. {
  27. var element = e.Current;
  28. if (!predicate(element))
  29. {
  30. yield return element;
  31. while (await e.MoveNextAsync())
  32. {
  33. yield return e.Current;
  34. }
  35. yield break;
  36. }
  37. }
  38. }
  39. finally
  40. {
  41. await e.DisposeAsync();
  42. }
  43. }
  44. #else
  45. return new SkipWhileAsyncIterator<TSource>(source, predicate);
  46. #endif
  47. }
  48. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
  49. {
  50. if (source == null)
  51. throw Error.ArgumentNull(nameof(source));
  52. if (predicate == null)
  53. throw Error.ArgumentNull(nameof(predicate));
  54. #if USE_ASYNC_ITERATOR
  55. return Create(Core);
  56. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  57. {
  58. var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false);
  59. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  60. {
  61. var index = -1;
  62. while (await e.MoveNextAsync())
  63. {
  64. checked
  65. {
  66. index++;
  67. }
  68. var element = e.Current;
  69. if (!predicate(element, index))
  70. {
  71. yield return element;
  72. while (await e.MoveNextAsync())
  73. {
  74. yield return e.Current;
  75. }
  76. yield break;
  77. }
  78. }
  79. }
  80. finally
  81. {
  82. await e.DisposeAsync();
  83. }
  84. }
  85. #else
  86. return new SkipWhileWithIndexAsyncIterator<TSource>(source, predicate);
  87. #endif
  88. }
  89. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate)
  90. {
  91. if (source == null)
  92. throw Error.ArgumentNull(nameof(source));
  93. if (predicate == null)
  94. throw Error.ArgumentNull(nameof(predicate));
  95. #if USE_ASYNC_ITERATOR
  96. return Create(Core);
  97. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  98. {
  99. var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false);
  100. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  101. {
  102. while (await e.MoveNextAsync())
  103. {
  104. var element = e.Current;
  105. if (!await predicate(element).ConfigureAwait(false))
  106. {
  107. yield return element;
  108. while (await e.MoveNextAsync())
  109. {
  110. yield return e.Current;
  111. }
  112. yield break;
  113. }
  114. }
  115. }
  116. finally
  117. {
  118. await e.DisposeAsync();
  119. }
  120. }
  121. #else
  122. return new SkipWhileAsyncIteratorWithTask<TSource>(source, predicate);
  123. #endif
  124. }
  125. #if !NO_DEEP_CANCELLATION
  126. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate)
  127. {
  128. if (source == null)
  129. throw Error.ArgumentNull(nameof(source));
  130. if (predicate == null)
  131. throw Error.ArgumentNull(nameof(predicate));
  132. #if USE_ASYNC_ITERATOR
  133. return Create(Core);
  134. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  135. {
  136. var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false);
  137. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  138. {
  139. while (await e.MoveNextAsync())
  140. {
  141. var element = e.Current;
  142. if (!await predicate(element, cancellationToken).ConfigureAwait(false))
  143. {
  144. yield return element;
  145. while (await e.MoveNextAsync())
  146. {
  147. yield return e.Current;
  148. }
  149. yield break;
  150. }
  151. }
  152. }
  153. finally
  154. {
  155. await e.DisposeAsync();
  156. }
  157. }
  158. #else
  159. return new SkipWhileAsyncIteratorWithTaskAndCancellation<TSource>(source, predicate);
  160. #endif
  161. }
  162. #endif
  163. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<bool>> predicate)
  164. {
  165. if (source == null)
  166. throw Error.ArgumentNull(nameof(source));
  167. if (predicate == null)
  168. throw Error.ArgumentNull(nameof(predicate));
  169. #if USE_ASYNC_ITERATOR
  170. return Create(Core);
  171. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  172. {
  173. var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false);
  174. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  175. {
  176. var index = -1;
  177. while (await e.MoveNextAsync())
  178. {
  179. checked
  180. {
  181. index++;
  182. }
  183. var element = e.Current;
  184. if (!await predicate(element, index).ConfigureAwait(false))
  185. {
  186. yield return element;
  187. while (await e.MoveNextAsync())
  188. {
  189. yield return e.Current;
  190. }
  191. yield break;
  192. }
  193. }
  194. }
  195. finally
  196. {
  197. await e.DisposeAsync();
  198. }
  199. }
  200. #else
  201. return new SkipWhileWithIndexAsyncIteratorWithTask<TSource>(source, predicate);
  202. #endif
  203. }
  204. #if !NO_DEEP_CANCELLATION
  205. public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<bool>> predicate)
  206. {
  207. if (source == null)
  208. throw Error.ArgumentNull(nameof(source));
  209. if (predicate == null)
  210. throw Error.ArgumentNull(nameof(predicate));
  211. #if USE_ASYNC_ITERATOR
  212. return Create(Core);
  213. async IAsyncEnumerator<TSource> Core(CancellationToken cancellationToken)
  214. {
  215. var e = source.GetConfiguredAsyncEnumerator(cancellationToken, false);
  216. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  217. {
  218. var index = -1;
  219. while (await e.MoveNextAsync())
  220. {
  221. checked
  222. {
  223. index++;
  224. }
  225. var element = e.Current;
  226. if (!await predicate(element, index, cancellationToken).ConfigureAwait(false))
  227. {
  228. yield return element;
  229. while (await e.MoveNextAsync())
  230. {
  231. yield return e.Current;
  232. }
  233. yield break;
  234. }
  235. }
  236. }
  237. finally
  238. {
  239. await e.DisposeAsync();
  240. }
  241. }
  242. #else
  243. return new SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation<TSource>(source, predicate);
  244. #endif
  245. }
  246. #endif
  247. #if !USE_ASYNC_ITERATOR
  248. private sealed class SkipWhileAsyncIterator<TSource> : AsyncIterator<TSource>
  249. {
  250. private readonly Func<TSource, bool> _predicate;
  251. private readonly IAsyncEnumerable<TSource> _source;
  252. private bool _doMoveNext;
  253. private IAsyncEnumerator<TSource> _enumerator;
  254. public SkipWhileAsyncIterator(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
  255. {
  256. Debug.Assert(predicate != null);
  257. Debug.Assert(source != null);
  258. _source = source;
  259. _predicate = predicate;
  260. }
  261. public override AsyncIteratorBase<TSource> Clone()
  262. {
  263. return new SkipWhileAsyncIterator<TSource>(_source, _predicate);
  264. }
  265. public override async ValueTask DisposeAsync()
  266. {
  267. if (_enumerator != null)
  268. {
  269. await _enumerator.DisposeAsync().ConfigureAwait(false);
  270. _enumerator = null;
  271. }
  272. await base.DisposeAsync().ConfigureAwait(false);
  273. }
  274. protected override async ValueTask<bool> MoveNextCore()
  275. {
  276. switch (_state)
  277. {
  278. case AsyncIteratorState.Allocated:
  279. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  280. // skip elements as requested
  281. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  282. {
  283. var element = _enumerator.Current;
  284. if (!_predicate(element))
  285. {
  286. _doMoveNext = false;
  287. _state = AsyncIteratorState.Iterating;
  288. goto case AsyncIteratorState.Iterating;
  289. }
  290. }
  291. break;
  292. case AsyncIteratorState.Iterating:
  293. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  294. {
  295. _current = _enumerator.Current;
  296. return true;
  297. }
  298. if (!_doMoveNext)
  299. {
  300. _current = _enumerator.Current;
  301. _doMoveNext = true;
  302. return true;
  303. }
  304. break;
  305. }
  306. await DisposeAsync().ConfigureAwait(false);
  307. return false;
  308. }
  309. }
  310. private sealed class SkipWhileWithIndexAsyncIterator<TSource> : AsyncIterator<TSource>
  311. {
  312. private readonly Func<TSource, int, bool> _predicate;
  313. private readonly IAsyncEnumerable<TSource> _source;
  314. private bool _doMoveNext;
  315. private IAsyncEnumerator<TSource> _enumerator;
  316. private int _index;
  317. public SkipWhileWithIndexAsyncIterator(IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
  318. {
  319. Debug.Assert(predicate != null);
  320. Debug.Assert(source != null);
  321. _source = source;
  322. _predicate = predicate;
  323. }
  324. public override AsyncIteratorBase<TSource> Clone()
  325. {
  326. return new SkipWhileWithIndexAsyncIterator<TSource>(_source, _predicate);
  327. }
  328. public override async ValueTask DisposeAsync()
  329. {
  330. if (_enumerator != null)
  331. {
  332. await _enumerator.DisposeAsync().ConfigureAwait(false);
  333. _enumerator = null;
  334. }
  335. await base.DisposeAsync().ConfigureAwait(false);
  336. }
  337. protected override async ValueTask<bool> MoveNextCore()
  338. {
  339. switch (_state)
  340. {
  341. case AsyncIteratorState.Allocated:
  342. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  343. _index = -1;
  344. // skip elements as requested
  345. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  346. {
  347. var element = _enumerator.Current;
  348. checked
  349. {
  350. _index++;
  351. }
  352. if (!_predicate(element, _index))
  353. {
  354. _doMoveNext = false;
  355. _state = AsyncIteratorState.Iterating;
  356. goto case AsyncIteratorState.Iterating;
  357. }
  358. }
  359. break;
  360. case AsyncIteratorState.Iterating:
  361. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  362. {
  363. _current = _enumerator.Current;
  364. return true;
  365. }
  366. if (!_doMoveNext)
  367. {
  368. _current = _enumerator.Current;
  369. _doMoveNext = true;
  370. return true;
  371. }
  372. break;
  373. }
  374. await DisposeAsync().ConfigureAwait(false);
  375. return false;
  376. }
  377. }
  378. private sealed class SkipWhileAsyncIteratorWithTask<TSource> : AsyncIterator<TSource>
  379. {
  380. private readonly Func<TSource, ValueTask<bool>> _predicate;
  381. private readonly IAsyncEnumerable<TSource> _source;
  382. private bool _doMoveNext;
  383. private IAsyncEnumerator<TSource> _enumerator;
  384. public SkipWhileAsyncIteratorWithTask(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<bool>> predicate)
  385. {
  386. Debug.Assert(predicate != null);
  387. Debug.Assert(source != null);
  388. _source = source;
  389. _predicate = predicate;
  390. }
  391. public override AsyncIteratorBase<TSource> Clone()
  392. {
  393. return new SkipWhileAsyncIteratorWithTask<TSource>(_source, _predicate);
  394. }
  395. public override async ValueTask DisposeAsync()
  396. {
  397. if (_enumerator != null)
  398. {
  399. await _enumerator.DisposeAsync().ConfigureAwait(false);
  400. _enumerator = null;
  401. }
  402. await base.DisposeAsync().ConfigureAwait(false);
  403. }
  404. protected override async ValueTask<bool> MoveNextCore()
  405. {
  406. switch (_state)
  407. {
  408. case AsyncIteratorState.Allocated:
  409. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  410. // skip elements as requested
  411. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  412. {
  413. var element = _enumerator.Current;
  414. if (!await _predicate(element).ConfigureAwait(false))
  415. {
  416. _doMoveNext = false;
  417. _state = AsyncIteratorState.Iterating;
  418. goto case AsyncIteratorState.Iterating;
  419. }
  420. }
  421. break;
  422. case AsyncIteratorState.Iterating:
  423. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  424. {
  425. _current = _enumerator.Current;
  426. return true;
  427. }
  428. if (!_doMoveNext)
  429. {
  430. _current = _enumerator.Current;
  431. _doMoveNext = true;
  432. return true;
  433. }
  434. break;
  435. }
  436. await DisposeAsync().ConfigureAwait(false);
  437. return false;
  438. }
  439. }
  440. #if !NO_DEEP_CANCELLATION
  441. private sealed class SkipWhileAsyncIteratorWithTaskAndCancellation<TSource> : AsyncIterator<TSource>
  442. {
  443. private readonly Func<TSource, CancellationToken, ValueTask<bool>> _predicate;
  444. private readonly IAsyncEnumerable<TSource> _source;
  445. private bool _doMoveNext;
  446. private IAsyncEnumerator<TSource> _enumerator;
  447. public SkipWhileAsyncIteratorWithTaskAndCancellation(IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<bool>> predicate)
  448. {
  449. Debug.Assert(predicate != null);
  450. Debug.Assert(source != null);
  451. _source = source;
  452. _predicate = predicate;
  453. }
  454. public override AsyncIteratorBase<TSource> Clone()
  455. {
  456. return new SkipWhileAsyncIteratorWithTaskAndCancellation<TSource>(_source, _predicate);
  457. }
  458. public override async ValueTask DisposeAsync()
  459. {
  460. if (_enumerator != null)
  461. {
  462. await _enumerator.DisposeAsync().ConfigureAwait(false);
  463. _enumerator = null;
  464. }
  465. await base.DisposeAsync().ConfigureAwait(false);
  466. }
  467. protected override async ValueTask<bool> MoveNextCore()
  468. {
  469. switch (_state)
  470. {
  471. case AsyncIteratorState.Allocated:
  472. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  473. // skip elements as requested
  474. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  475. {
  476. var element = _enumerator.Current;
  477. if (!await _predicate(element, _cancellationToken).ConfigureAwait(false))
  478. {
  479. _doMoveNext = false;
  480. _state = AsyncIteratorState.Iterating;
  481. goto case AsyncIteratorState.Iterating;
  482. }
  483. }
  484. break;
  485. case AsyncIteratorState.Iterating:
  486. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  487. {
  488. _current = _enumerator.Current;
  489. return true;
  490. }
  491. if (!_doMoveNext)
  492. {
  493. _current = _enumerator.Current;
  494. _doMoveNext = true;
  495. return true;
  496. }
  497. break;
  498. }
  499. await DisposeAsync().ConfigureAwait(false);
  500. return false;
  501. }
  502. }
  503. #endif
  504. private sealed class SkipWhileWithIndexAsyncIteratorWithTask<TSource> : AsyncIterator<TSource>
  505. {
  506. private readonly Func<TSource, int, ValueTask<bool>> _predicate;
  507. private readonly IAsyncEnumerable<TSource> _source;
  508. private bool _doMoveNext;
  509. private IAsyncEnumerator<TSource> _enumerator;
  510. private int _index;
  511. public SkipWhileWithIndexAsyncIteratorWithTask(IAsyncEnumerable<TSource> source, Func<TSource, int, ValueTask<bool>> predicate)
  512. {
  513. Debug.Assert(predicate != null);
  514. Debug.Assert(source != null);
  515. _source = source;
  516. _predicate = predicate;
  517. }
  518. public override AsyncIteratorBase<TSource> Clone()
  519. {
  520. return new SkipWhileWithIndexAsyncIteratorWithTask<TSource>(_source, _predicate);
  521. }
  522. public override async ValueTask DisposeAsync()
  523. {
  524. if (_enumerator != null)
  525. {
  526. await _enumerator.DisposeAsync().ConfigureAwait(false);
  527. _enumerator = null;
  528. }
  529. await base.DisposeAsync().ConfigureAwait(false);
  530. }
  531. protected override async ValueTask<bool> MoveNextCore()
  532. {
  533. switch (_state)
  534. {
  535. case AsyncIteratorState.Allocated:
  536. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  537. _index = -1;
  538. // skip elements as requested
  539. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  540. {
  541. var element = _enumerator.Current;
  542. checked
  543. {
  544. _index++;
  545. }
  546. if (!await _predicate(element, _index).ConfigureAwait(false))
  547. {
  548. _doMoveNext = false;
  549. _state = AsyncIteratorState.Iterating;
  550. goto case AsyncIteratorState.Iterating;
  551. }
  552. }
  553. break;
  554. case AsyncIteratorState.Iterating:
  555. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  556. {
  557. _current = _enumerator.Current;
  558. return true;
  559. }
  560. if (!_doMoveNext)
  561. {
  562. _current = _enumerator.Current;
  563. _doMoveNext = true;
  564. return true;
  565. }
  566. break;
  567. }
  568. await DisposeAsync().ConfigureAwait(false);
  569. return false;
  570. }
  571. }
  572. #if !NO_DEEP_CANCELLATION
  573. private sealed class SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation<TSource> : AsyncIterator<TSource>
  574. {
  575. private readonly Func<TSource, int, CancellationToken, ValueTask<bool>> _predicate;
  576. private readonly IAsyncEnumerable<TSource> _source;
  577. private bool _doMoveNext;
  578. private IAsyncEnumerator<TSource> _enumerator;
  579. private int _index;
  580. public SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation(IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, ValueTask<bool>> predicate)
  581. {
  582. Debug.Assert(predicate != null);
  583. Debug.Assert(source != null);
  584. _source = source;
  585. _predicate = predicate;
  586. }
  587. public override AsyncIteratorBase<TSource> Clone()
  588. {
  589. return new SkipWhileWithIndexAsyncIteratorWithTaskAndCancellation<TSource>(_source, _predicate);
  590. }
  591. public override async ValueTask DisposeAsync()
  592. {
  593. if (_enumerator != null)
  594. {
  595. await _enumerator.DisposeAsync().ConfigureAwait(false);
  596. _enumerator = null;
  597. }
  598. await base.DisposeAsync().ConfigureAwait(false);
  599. }
  600. protected override async ValueTask<bool> MoveNextCore()
  601. {
  602. switch (_state)
  603. {
  604. case AsyncIteratorState.Allocated:
  605. _enumerator = _source.GetAsyncEnumerator(_cancellationToken);
  606. _index = -1;
  607. // skip elements as requested
  608. while (await _enumerator.MoveNextAsync().ConfigureAwait(false))
  609. {
  610. var element = _enumerator.Current;
  611. checked
  612. {
  613. _index++;
  614. }
  615. if (!await _predicate(element, _index, _cancellationToken).ConfigureAwait(false))
  616. {
  617. _doMoveNext = false;
  618. _state = AsyncIteratorState.Iterating;
  619. goto case AsyncIteratorState.Iterating;
  620. }
  621. }
  622. break;
  623. case AsyncIteratorState.Iterating:
  624. if (_doMoveNext && await _enumerator.MoveNextAsync().ConfigureAwait(false))
  625. {
  626. _current = _enumerator.Current;
  627. return true;
  628. }
  629. if (!_doMoveNext)
  630. {
  631. _current = _enumerator.Current;
  632. _doMoveNext = true;
  633. return true;
  634. }
  635. break;
  636. }
  637. await DisposeAsync().ConfigureAwait(false);
  638. return false;
  639. }
  640. }
  641. #endif
  642. #endif
  643. }
  644. }