| @@ -269,6 +269,7 @@ public void Dispose() |
|
|
| 269 |
269 |
} |
| 270 |
270 |
OnCloseEcho(); |
| 271 |
271 |
_arena.Dispose(); |
|
272 |
+_reusableFlushSyncTokenSource?.Dispose(); |
| 272 |
273 |
GC.SuppressFinalize(this); |
| 273 |
274 |
} |
| 274 |
275 |
|
| @@ -872,31 +873,37 @@ private async ValueTask FlushAsync_Awaited(PhysicalConnection conne |
|
|
| 872 |
873 |
} |
| 873 |
874 |
} |
| 874 |
875 |
|
|
876 |
+CancellationTokenSource _reusableFlushSyncTokenSource; |
| 875 |
877 |
[Obsolete("this is an anti-pattern; work to reduce reliance on this is in progress")] |
| 876 |
878 |
internal WriteResult FlushSync(bool throwOnFailure, int millisecondsTimeout) |
| 877 |
879 |
{ |
| 878 |
|
-using (var source = new CancellationTokenSource()) |
|
880 |
+var cts = _reusableFlushSyncTokenSource ??= new CancellationTokenSource(); |
|
881 |
+var flush = FlushAsync(throwOnFailure, cts.Token); |
|
882 |
+if (!flush.IsCompletedSuccessfully) |
| 879 |
883 |
{ |
| 880 |
|
-source.CancelAfter(TimeSpan.FromMilliseconds(millisecondsTimeout)); |
| 881 |
|
-var flush = FlushAsync(throwOnFailure, source.Token); |
| 882 |
|
-if (!flush.IsCompletedSuccessfully) |
|
884 |
+// only schedule cancellation if it doesn't complete synchronously; at this point, it is doomed |
|
885 |
+_reusableFlushSyncTokenSource = null; |
|
886 |
+cts.CancelAfter(TimeSpan.FromMilliseconds(millisecondsTimeout)); |
|
887 |
+try |
| 883 |
888 |
{ |
| 884 |
|
-try |
| 885 |
|
-{ |
| 886 |
|
- // here lies the evil |
| 887 |
|
- flush.AsTask().Wait(); |
| 888 |
|
- } |
| 889 |
|
-catch (AggregateException ex) |
|
889 |
+// here lies the evil |
|
890 |
+flush.AsTask().Wait(); |
|
891 |
+} |
|
892 |
+catch (AggregateException ex) |
|
893 |
+{ |
|
894 |
+if (ex.InnerExceptions.Any(e => e is TaskCanceledException)) |
| 890 |
895 |
{ |
| 891 |
|
-if (ex.InnerExceptions.Any(e => e is TaskCanceledException)) |
| 892 |
|
-{ |
| 893 |
|
-ThrowTimeout(); |
| 894 |
|
-} |
| 895 |
|
-throw; |
|
896 |
+ThrowTimeout(); |
| 896 |
897 |
} |
|
898 |
+throw; |
|
899 |
+} |
|
900 |
+finally |
|
901 |
+{ |
|
902 |
+cts.Dispose(); |
| 897 |
903 |
} |
| 898 |
|
-return flush.Result; |
| 899 |
904 |
} |
|
905 |
+return flush.Result; |
|
906 |
+ |
| 900 |
907 |
void ThrowTimeout() |
| 901 |
908 |
{ |
| 902 |
909 |
#if DEBUG |