I'm developing a WPF application in C# that interfaces with local and IP cameras, utilizing AForge.Video.DirectShow and CancellationTokenSource to handle tasks related to video capture. For tracking tasks for each camera, I use a Dictionary with camera index as key and CancellationTokenSource as value.
The problem I'm facing is that the Dictionary does not seem to be maintaining state as expected. I store a new CancellationTokenSource when a new task is created, but when I try to retrieve it with the same key later, it's not found in the Dictionary.
Here's the relevant section of my code. tokenSources is a Dictionary<int, CancellationTokenSource> that I use to store cancellation tokens for different tasks.
private async void LocalCamera_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
System.Windows.Controls.ComboBox comboBoxCamera = sender as System.Windows.Controls.ComboBox;
int cameraIndex = int.Parse(SourceComboBox.Name.Replace("comboBox", ""));
int selectedItemIndex = comboBoxCamera.SelectedIndex;
Image imageControl = comboBoxCamera.Tag as Image;
Debug.WriteLine($"selectedItemIndex: {selectedItemIndex}");
Debug.WriteLine($"cameraIndex: {cameraIndex}");
Debug.WriteLine($"tokenSources contains cameraIndex: {tokenSources.ContainsKey(cameraIndex)}");
// If selectedItemIndex is 0, cancel the current task if it's running
if (selectedItemIndex == 0)
{
if (tokenSources.ContainsKey(cameraIndex))
{
var cts = tokenSources[cameraIndex];
cts.Cancel();
cts.Dispose();
tokenSources.Remove(cameraIndex);
Debug.WriteLine($"CancellationTokenSource for cameraIndex {cameraIndex} cancelled and removed.");
}
}
else
{
// If selectedItemIndex is greater than 0, start a new task
var newCts = new CancellationTokenSource();
tokenSources[cameraIndex] = newCts;
Debug.WriteLine($"New CancellationTokenSource created and stored for cameraIndex {cameraIndex}.");
await Task.Factory.StartNew(() => LocalCameraService.Instance.CaptureCameraCallback(selectedItemIndex - 1, SourceImageControl, newCts.Token), newCts.Token, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
Debug.WriteLine($"tokenSources count after operations: {tokenSources.Count}");
}
The issue arises when I'm trying to interact with tokenSources:
When I store a new CancellationTokenSource for cameraIndex, the tokenSources Dictionary count increases to 1, as expected. However, when I check tokenSources.ContainsKey(cameraIndex) for the same cameraIndex later, it returns False, which is not expected. I have confirmed that cameraIndex is not changing unexpectedly, and I don't see anywhere in my code where tokenSources is being re-initialized. The program does not seem to maintain the state of the tokenSources Dictionary across different calls to the LocalCamera_ComboBox_SelectionChanged method.
I've tried to debug this issue by inserting various debug messages and using breakpoints, but I can't find any point where tokenSources is getting cleared or re-initialized.
I'm not sure if I'm missing something related to the lifecycle of WPF components, the use of Dictionaries, or asynchronous programming with tasks and cancellation tokens. Any insights would be greatly appreciated.
It appears to me that you need to change this line of code:
int cameraIndex = int.Parse(SourceComboBox.Name.Replace("comboBox", ""));
to this:
int cameraIndex = int.Parse(comboBoxCamera.Name.Replace("comboBox", ""));
I would be using a different approach here.
private async void LocalCamera_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var comboboxes = new ComboBox[]
{
comboBox1, comboBox2,
comboBox3, comboBox4,
};
System.Windows.Controls.ComboBox comboBoxCamera = sender as System.Windows.Controls.ComboBox;
int cameraIndex = Array.IndexOf(comboboxes, comboBoxCamera);