提问人:Captain C 提问时间:11/5/2023 最后编辑:Captain C 更新时间:11/6/2023 访问量:36
如何在C#中取消任务之前在WebSocket上发送消息?
How to Send a Message on a WebSocket Before Task Cancellation in C#?
问:
我有一个处理 IP 摄像机流的异步方法 (IPCameraMethod)。它启动和取消通过 WebSocket 管理这些流的任务。这些任务在单独的类 IPCameraService 及其 Main 方法中启动。
当我尝试使用 CancellationToken 取消任务时,关联的 WebSocket 会立即关闭,从而阻止我发送应在 WebSocket 关闭之前执行的“Stop_Stream”命令。此“Stop_Stream”消息对于在服务器端正常关闭流至关重要。
这是我的代码的简化版本:
internal static Dictionary<int, Tuple<int, CancellationTokenSource, Task, CameraType>> tokenSources = new Dictionary<int, Tuple<int, CancellationTokenSource, Task, CameraType>>();
在 DeviceSettings 类中:
private async Task IPCameraMethod()
{
if (string.IsNullOrWhiteSpace(textBoxUrl.Text) ||
!int.TryParse(SourceComboBox.Name.Replace("comboBox", ""), out int cameraIndex) ||
comboBoxSavedCameras.SelectedIndex < 0)
{
return;
}
string url = textBoxUrl.Text;
int selectedItemIndex = comboBoxSavedCameras.SelectedIndex;
if (tokenSources.TryGetValue(cameraIndex, out var tuple))
{
if (selectedItemIndex != tuple.Item1)
{
tuple.Item2.Cancel();
try
{
await tuple.Item3; // Await the task's completion
}
catch (OperationCanceledException)
{
// Task was cancelled, expected behavior
}
tuple.Item2.Dispose();
tokenSources.Remove(cameraIndex);
}
else
{
return; // If selected item is the same, we do not need to create a new task
}
}
// Now that the old task has been cancelled and awaited, start the new task.
var newCts = new CancellationTokenSource();
Task newTask = null;
if (Camera != null)
{
newTask = new TaskFactory().StartNew(() => Camera.IPCameraService.Main(SourceImageControl, selectedItemIndex, newCts.Token, url));
}
else
{
newTask = new TaskFactory().StartNew(() => (BaseViewModel as AddFaceViewModel).IPCameraService.Main(SourceImageControl, selectedItemIndex, newCts.Token, url));
}
Debug.WriteLine("New Task Created!");
tokenSources[cameraIndex] = Tuple.Create(selectedItemIndex, newCts, newTask, CameraType.IP);
}
在 IPCameraService 类中:
public async Task Main(System.Windows.Controls.Image imageControl, int cameraIndex, CancellationToken token, string cameraUrl)
{
CameraURLs[cameraIndex] = cameraUrl;
await StartSocket(cameraIndex, token);
await StartStream(cameraIndex, cameraUrl, token);
var stopStreamCompletion = new TaskCompletionSource<bool>();
EventHandler(cameraUrl, cameraIndex, token);
while (!token.IsCancellationRequested) // Added a token check to allow stopping the loop externally
{
var frame = await RunYolo(cameraIndex, token);
if (frame != null)
await UpdateDisplay(frame, imageControl, token);
}
var Stop_Server = new
{
command = "Stop_Stream"
};
var ws = CameraWebsockets[cameraIndex];
var Start_ServerJson = JsonConvert.SerializeObject(Stop_Server);
var Start_ServerBytes = Encoding.UTF8.GetBytes(Start_ServerJson);
await ws.SendAsync(new ArraySegment<byte>(Start_ServerBytes, 0, Start_ServerBytes.Length), WebSocketMessageType.Text, true, token);
Debug.WriteLine("Websocket Cleared!");
}
问题出在 上,它旨在取消正在进行的任务并立即启动清理序列。我需要在进行此清理之前发送“Stop_Stream”命令,但是一旦请求取消,WebSocket就会关闭。tuple.Item2.Cancel();
如何重组取消和清理逻辑,以允许在关闭 WebSocket 之前发送“Stop_Stream”消息?
我尝试过:
- 我试图捕捉OperationCanceledException,希望 WebSocket 仍将打开以发送消息,但它已经 到那时关闭。
- 将 WebSocket 发送逻辑移动到 catch 块不起作用 或者,因为取消后无法访问 WebSocket。
问题:
- 如何确保在 WebSocket 上发送“Stop_Stream”消息 在取消任务之前,实际导致 WebSocket 关闭?
其他上下文:
IPCameraMethod 和 Main 方法位于不同的类中,其中 IPCameraMethod 调用 Main 方法。 WebSocket 连接至关重要,在发送“Stop_Stream”命令之前应保持打开状态。 正在使用 C# .NET Framework 4.7.2。
答: 暂无答案
评论