Skip to content

Commit 257d461

Browse files
committed
introduce dispose pattern
1 parent 1d668c7 commit 257d461

File tree

3 files changed

+105
-36
lines changed

3 files changed

+105
-36
lines changed

src/KubernetesClient/StreamDemuxer.cs

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class StreamDemuxer : IStreamDemuxer
2929
private readonly StreamType streamType;
3030
private readonly bool ownsSocket;
3131
private Task runLoop;
32+
private bool disposedValue;
3233

3334
/// <summary>
3435
/// Initializes a new instance of the <see cref="StreamDemuxer"/> class.
@@ -61,29 +62,7 @@ public void Start()
6162
this.runLoop = Task.Run(async () => await RunLoop(cts.Token).ConfigureAwait(false));
6263
}
6364

64-
/// <inheritdoc/>
65-
public void Dispose()
66-
{
67-
try
68-
{
69-
if (this.runLoop != null)
70-
{
71-
this.cts.Cancel();
72-
this.runLoop.Wait();
73-
}
74-
}
75-
catch (Exception ex)
76-
{
77-
// Dispose methods can never throw.
78-
Debug.Write(ex);
79-
}
80-
81-
if (this.ownsSocket)
82-
{
83-
this.webSocket.Dispose();
84-
}
85-
}
86-
65+
8766
/// <summary>
8867
/// Gets a <see cref="Stream"/> which allows you to read to and/or write from a remote channel.
8968
/// </summary>
@@ -276,5 +255,49 @@ protected async Task RunLoop(CancellationToken cancellationToken)
276255
this.ConnectionClosed?.Invoke(this, EventArgs.Empty);
277256
}
278257
}
258+
259+
protected virtual void Dispose(bool disposing)
260+
{
261+
if (!disposedValue)
262+
{
263+
if (disposing)
264+
{
265+
try
266+
{
267+
if (this.runLoop != null)
268+
{
269+
this.cts.Cancel();
270+
this.runLoop.Wait();
271+
}
272+
}
273+
catch (Exception ex)
274+
{
275+
// Dispose methods can never throw.
276+
Debug.Write(ex);
277+
}
278+
279+
if (this.ownsSocket)
280+
{
281+
this.webSocket.Dispose();
282+
}
283+
}
284+
285+
disposedValue = true;
286+
}
287+
}
288+
289+
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
290+
// ~StreamDemuxer()
291+
// {
292+
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
293+
// Dispose(disposing: false);
294+
// }
295+
296+
public void Dispose()
297+
{
298+
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
299+
Dispose(disposing: true);
300+
GC.SuppressFinalize(this);
301+
}
279302
}
280303
}

src/KubernetesClient/Watcher.cs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public class Watcher<T> : IDisposable
4242
private readonly Func<Task<TextReader>> _streamReaderCreator;
4343

4444
private TextReader _streamReader;
45+
private bool disposedValue;
4546
private readonly Task _watcherLoop;
4647

4748
/// <summary>
@@ -94,13 +95,6 @@ public Watcher(Func<Task<TextReader>> streamReaderCreator, Action<WatchEventType
9495
_watcherLoop = Task.Run(async () => await WatcherLoop(_cts.Token).ConfigureAwait(false));
9596
}
9697

97-
/// <inheritdoc/>
98-
public void Dispose()
99-
{
100-
_cts.Cancel();
101-
_streamReader?.Dispose();
102-
}
103-
10498
/// <summary>
10599
/// add/remove callbacks when any event raised from api server
106100
/// </summary>
@@ -174,5 +168,33 @@ private async Task WatcherLoop(CancellationToken cancellationToken)
174168
OnClosed?.Invoke();
175169
}
176170
}
171+
172+
protected virtual void Dispose(bool disposing)
173+
{
174+
if (!disposedValue)
175+
{
176+
if (disposing)
177+
{
178+
_cts.Cancel();
179+
_streamReader?.Dispose();
180+
}
181+
182+
disposedValue = true;
183+
}
184+
}
185+
186+
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
187+
// ~Watcher()
188+
// {
189+
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
190+
// Dispose(disposing: false);
191+
// }
192+
193+
public void Dispose()
194+
{
195+
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
196+
Dispose(disposing: true);
197+
GC.SuppressFinalize(this);
198+
}
177199
}
178200
}

tests/KubernetesClient.Tests/WebSocketTestBase.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public abstract class WebSocketTestBase : IDisposable
2525
/// The next server port to use.
2626
/// </summary>
2727
private static int nextPort = 13255;
28-
28+
private bool disposedValue;
2929
private readonly ITestOutputHelper testOutput;
3030

3131
/// <summary>
@@ -315,11 +315,7 @@ await webSocket.SendAsync(sendBuffer, WebSocketMessageType.Binary,
315315
totalBytes: receivedData.Length);
316316
}
317317

318-
public void Dispose()
319-
{
320-
this.CancellationSource.Dispose();
321-
this.Host.Dispose();
322-
}
318+
323319

324320
/// <summary>
325321
/// A <see cref="ServiceClientCredentials"/> implementation representing no credentials (i.e. anonymous).
@@ -350,5 +346,33 @@ protected static class EventIds
350346
/// </summary>
351347
private static readonly EventId ErrorClosingServerSocket = new EventId(1000, nameof(ErrorClosingServerSocket));
352348
}
349+
350+
protected virtual void Dispose(bool disposing)
351+
{
352+
if (!disposedValue)
353+
{
354+
if (disposing)
355+
{
356+
CancellationSource.Dispose();
357+
Host.Dispose();
358+
}
359+
360+
disposedValue = true;
361+
}
362+
}
363+
364+
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
365+
// ~WebSocketTestBase()
366+
// {
367+
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
368+
// Dispose(disposing: false);
369+
// }
370+
371+
public void Dispose()
372+
{
373+
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
374+
Dispose(disposing: true);
375+
GC.SuppressFinalize(this);
376+
}
353377
}
354378
}

0 commit comments

Comments
 (0)