I have a C# application where I manage multiple IP cameras. Each camera runs a task that performs a series of operations like starting a socket, streaming data, and running an object detection model. I manage these tasks using a dictionary that holds the camera index and its corresponding CancellationTokenSource.
My issue is that when I change the settings for a camera, I want to first
cancel the existing task for that camera and then
start a new one. However, it seems like the new task starts before the old one finishes clearing, and this creates problems.
Here's the sample code:
Main method that starts the task for a camera:
internal static Dictionary<int, Tuple<int, CancellationTokenSource>> tokenSources = new Dictionary<int, Tuple<int, CancellationTokenSource>>();
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();
tuple.Item2.Dispose();
tokenSources.Remove(cameraIndex);
}
}
var newCts = new CancellationTokenSource();
tokenSources[cameraIndex] = Tuple.Create(selectedItemIndex, newCts);
Debug.WriteLine("CREATING NEW TASK");
await Task.Factory.StartNew(() =>
Camera.IPCameraService.Main(SourceImageControl, selectedItemIndex, newCts.Token, url),
newCts.Token,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default
);
}
Task method being called
public async Task Main(System.Windows.Controls.Image imageControl, int cameraIndex, CancellationToken token, string cameraUrl)
{
CameraURLs[cameraIndex] = cameraUrl;
await StartSocket(cameraIndex);
await StartStream(cameraIndex, cameraUrl);
EventHandler(cameraUrl, cameraIndex);
while (!token.IsCancellationRequested)
{
var frame = await RunYolo(cameraIndex);
if (frame != null)
await UpdateDisplay(frame, imageControl);
}
if (token.IsCancellationRequested)
{
Debug.WriteLine("Clearing Websocket!");
var ws = CameraWebsockets[cameraIndex];
if (ws != null && ws.State == System.Net.WebSockets.WebSocketState.Open)
{
await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Cancellation requested", CancellationToken.None);
await Task.Delay(500);
}
}
}
Issue: The output I see is:
CREATING NEW TASK
Clearing Websocket!
I would expect to see "Clearing Websocket!" before "CREATING NEW TASK". How can I enforce this order?
Attempts:
I tried to wait for the task to complete using await but I'm still experiencing the issue.
Any help would be greatly appreciated!