diff --git a/src/AVEVA.Historian.Client/HistorianSession.cs b/src/AVEVA.Historian.Client/HistorianSession.cs
index 9873fa2..120bbe6 100644
--- a/src/AVEVA.Historian.Client/HistorianSession.cs
+++ b/src/AVEVA.Historian.Client/HistorianSession.cs
@@ -13,6 +13,7 @@ public sealed class HistorianSession : IAsyncDisposable
private readonly HistorianGrpcConnection _connection;
private readonly HistorianGrpcHandshake.Session _session;
private readonly HistorianClientOptions _options;
+ private int _disposed;
/// Whether this session was opened read-only or write-enabled (the Open2 connection mode).
public HistorianSessionKind Kind { get; }
@@ -41,6 +42,7 @@ public sealed class HistorianSession : IAsyncDisposable
int maxValues,
[EnumeratorCancellation] CancellationToken ct = default)
{
+ ct.ThrowIfCancellationRequested();
var orch = new HistorianGrpcReadOrchestrator(_options);
IReadOnlyList rows = await Task.Run(
() => orch.RunRawQueryOnSession(_connection, _session.ClientHandle, tag, startUtc, endUtc, maxValues, ct), ct)
@@ -63,6 +65,7 @@ public sealed class HistorianSession : IAsyncDisposable
TimeSpan interval,
[EnumeratorCancellation] CancellationToken ct = default)
{
+ ct.ThrowIfCancellationRequested();
var orch = new HistorianGrpcReadOrchestrator(_options);
IReadOnlyList rows = await Task.Run(
() => orch.RunAggregateQueryOnSession(_connection, _session.ClientHandle, tag, startUtc, endUtc, mode, interval, ct), ct)
@@ -180,7 +183,10 @@ public sealed class HistorianSession : IAsyncDisposable
/// also idle-expires on its own; this releases the local channel resources immediately.
public ValueTask DisposeAsync()
{
- _connection.Dispose();
+ if (Interlocked.Exchange(ref _disposed, 1) == 0)
+ {
+ _connection.Dispose();
+ }
return ValueTask.CompletedTask;
}
}