diff --git a/src/AR.Iec61850/Mms/MmsClientSession.ReceivePumpLifetime.cs b/src/AR.Iec61850/Mms/MmsClientSession.ReceivePumpLifetime.cs
new file mode 100644
index 0000000..148a97a
--- /dev/null
+++ b/src/AR.Iec61850/Mms/MmsClientSession.ReceivePumpLifetime.cs
@@ -0,0 +1,50 @@
+namespace AR.Iec61850.Mms;
+
+public sealed partial class MmsClientSession
+{
+ ///
+ /// Rebinds the confirmed-service receive pump to the MMS association lifetime instead
+ /// of the cancellation token that was used only to establish the connection.
+ /// Call this when a long-lived session will be reused across multiple UI operations.
+ ///
+ public async Task RebindReceivePumpToSessionLifetimeAsync(
+ CancellationToken cancellationToken = default)
+ {
+ EnsureMmsReady();
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (_receivePump.PendingOperationCount != 0)
+ {
+ throw new InvalidOperationException(
+ "The MMS receive pump cannot be rebound while confirmed operations are pending.");
+ }
+
+ await MmsReceivePumpLifetimePolicy.RebindAsync(
+ _receivePump,
+ cancellationToken).ConfigureAwait(false);
+
+ if (!IsTransportConnected || !IsMmsInitiated || !_receivePump.IsRunning)
+ {
+ throw new InvalidOperationException(
+ "The MMS receive pump could not be rebound to the active association lifetime.");
+ }
+
+ LastReceiveRoutingSummary =
+ "MMS receive pump rebound to association-owned lifetime for reusable confirmed services.";
+ }
+}
+
+internal static class MmsReceivePumpLifetimePolicy
+{
+ public static async Task RebindAsync(
+ MmsReceivePump receivePump,
+ CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(receivePump);
+ cancellationToken.ThrowIfCancellationRequested();
+
+ await receivePump.StopAsync().ConfigureAwait(false);
+ cancellationToken.ThrowIfCancellationRequested();
+ receivePump.Start();
+ }
+}
diff --git a/tests/AR.Iec61850.Tests/Mms/MmsReceivePumpLifetimePolicyTests.cs b/tests/AR.Iec61850.Tests/Mms/MmsReceivePumpLifetimePolicyTests.cs
new file mode 100644
index 0000000..0f49423
--- /dev/null
+++ b/tests/AR.Iec61850.Tests/Mms/MmsReceivePumpLifetimePolicyTests.cs
@@ -0,0 +1,49 @@
+using System.Threading.Channels;
+using AR.Iec61850.Asn1;
+using AR.Iec61850.Mms;
+
+namespace AR.Iec61850.Tests.Mms;
+
+public sealed class MmsReceivePumpLifetimePolicyTests
+{
+ [Fact]
+ public async Task Rebind_Detaches_Pump_From_Completed_Connect_Operation_Token()
+ {
+ var channel = Channel.CreateUnbounded();
+ var router = new MmsReceiveRouter();
+ var pump = new MmsReceivePump(
+ router,
+ cancellationToken => channel.Reader.ReadAsync(cancellationToken).AsTask());
+ using var connectOperation = new CancellationTokenSource();
+
+ pump.Start(connectOperation.Token);
+ await MmsReceivePumpLifetimePolicy.RebindAsync(pump);
+ connectOperation.Cancel();
+
+ using var pending = pump.RegisterConfirmedOperation(27);
+ await channel.Writer.WriteAsync(BuildConfirmedReadResponse(27));
+
+ using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(2));
+ var response = await pending.WaitAsync(timeout.Token);
+
+ Assert.True(pump.IsRunning);
+ Assert.Equal(MmsPduKind.ConfirmedResponse, response.Kind);
+ Assert.Equal(27, response.InvokeId);
+
+ await pump.StopAsync();
+ }
+
+ private static byte[] BuildConfirmedReadResponse(int invokeId)
+ {
+ var data = MmsDataCodec.Encode(MmsDataValue.Boolean(true));
+ var listOfAccessResult = BerWriter.EncodeTlv(0xA1, data);
+ var readService = BerWriter.EncodeTlv(0xA4, listOfAccessResult);
+ var mms = BerWriter.EncodeTlv(
+ 0xA1,
+ BerWriter.EncodeTlv(0x02, BerWriter.EncodeSignedInteger(invokeId))
+ .Concat(readService)
+ .ToArray());
+
+ return MmsPresentation.WrapIsoPresentationPData(mms);
+ }
+}