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!