diff --git a/Core/Remote/RemoteClient.cs b/Core/Remote/RemoteClient.cs
index 03c1e28..a04e09a 100644
--- a/Core/Remote/RemoteClient.cs
+++ b/Core/Remote/RemoteClient.cs
@@ -456,11 +456,12 @@ namespace JJServiceManager.Remote
var key = enabled ? $"{mode}|{port}" : "off";
if (key == _key) return;
_key = key;
+ bool wasRunning = _listener != null;
_listener?.Dispose();
_listener = null;
if (!enabled)
{
- _log("Passive 수신 중지", LogLevel.Info);
+ if (wasRunning) _log("Passive 수신 중지", LogLevel.Info);
return;
}
try
diff --git a/Core/Remote/RemoteServer.cs b/Core/Remote/RemoteServer.cs
index 22ef654..fa8c33b 100644
--- a/Core/Remote/RemoteServer.cs
+++ b/Core/Remote/RemoteServer.cs
@@ -399,7 +399,7 @@ namespace JJServiceManager.Remote
}
}
var old = Interlocked.Exchange(ref screen, null);
- old?.Stop();
+ EndScreen(old);
var s = new ScreenSession(Interlocked.Increment(ref _nextScreenId), whoNow, control, monitor);
screen = s;
_screens[s.Id] = s;
@@ -425,7 +425,7 @@ namespace JJServiceManager.Remote
case "screenStop":
{
var s = Interlocked.Exchange(ref screen, null);
- s?.Stop();
+ EndScreen(s);
await Reply(conn, id, result: new JsonObject());
break;
}
@@ -473,7 +473,7 @@ namespace JJServiceManager.Remote
streams.Clear();
}
var s = Interlocked.Exchange(ref screen, null);
- s?.Stop();
+ EndScreen(s);
conn.Dispose();
if (authed && who != peer) _log($"원격 연결 종료: {who}", LogLevel.Info);
}
@@ -544,7 +544,7 @@ namespace JJServiceManager.Remote
["w"] = w,
["h"] = h,
["data"] = Convert.ToBase64String(jpeg)
- }, s.Token).ConfigureAwait(false);
+ }, ct).ConfigureAwait(false); // 보내는 도중 취소하면 TLS 스트림이 깨지므로 화면 중지 토큰은 쓰지 않음
lastHash = hash;
lastMonitor = monitor;
lastSent = DateTime.UtcNow;
@@ -564,7 +564,11 @@ namespace JJServiceManager.Remote
_screens.TryRemove(s.Id, out _);
if (!conn.IsDisposed)
{
- try { await conn.SendAsync(new JsonObject { ["event"] = "screenEnd", ["sid"] = s.Id, ["reason"] = endReason }).ConfigureAwait(false); }
+ try
+ {
+ using var t = new CancellationTokenSource(TimeSpan.FromSeconds(5));
+ await conn.SendAsync(new JsonObject { ["event"] = "screenEnd", ["sid"] = s.Id, ["reason"] = endReason }, t.Token).ConfigureAwait(false);
+ }
catch { }
}
_log($"[원격 화면] {s.Who} 연결 끝", LogLevel.Info);
@@ -572,10 +576,18 @@ namespace JJServiceManager.Remote
}
}
+ /// 화면 연결 하나 끝내기 — 표시 막대는 바로 갱신
+ private void EndScreen(ScreenSession s)
+ {
+ if (s == null) return;
+ s.Stop();
+ if (_screens.TryRemove(s.Id, out _)) NotifyViewers();
+ }
+
/// 이 PC에서 [연결 끊기]를 눌렀을 때 모든 화면 연결 종료
public void StopAllScreens()
{
- foreach (var s in _screens.Values) s.Stop();
+ foreach (var s in _screens.Values.ToList()) EndScreen(s);
}
private void NotifyViewers()