ContextSwitchDeadlock

The CLR has been unable to transition from COM context 0x3322d98 to COM context 0x3322f08 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.

I’ve recently encountered this error and had a hard time figuring out why it popped up. I searched everywhere but most responses were “Debug -> Exceptions -> Managed Debug Assistants menu in Visual Studio and uncheck the ContextSwitchDeadlock” I’m not the type of person who ignores the problem. I like to get to the bottom of the problem.

During my research, I’ve read a few possibilities of why this error occurred. Just to mention a few:

The Main thread is doing heavy processing and your code isn’t handling this.

You might want to check the code for redundancy

You may be using an element from the Main Thread directly instead of using a variable

I was developing a Windows Form application in which a user could encrypt and decrypt a list of files. The problem was when the files were too big and the system tried to process it, after a minute the error would pop up. I noticed a few errors in my code along the way but here is the main problem:
I have a task running the encryption function and has the path of the file as a parameter.After the encryption finishes, it removes that item from the list. An example of this is:

//Error code example
for(int i = list.Items.Count - 1; i >0;i--){
var t = new Task(() => encryptionFunction(list.Items[i].Tostring(),destinationPath)); //This part gives an error
t.Start();
t.Wait();
//This part also gives an error
list.Items.RemoveAt(i);
list.Update();
}

At first I thought it was ‘list.Items[sourceIterator].Tostring()’, after saving it in a variable and replacing it the encryption worked just fine. I discovered that by using t.IsCompleted and t.IsFaulted it can solve my issue!
Example code:

for(int i = list.Items.Count - 1; i >0;i++){
var file = list.Items[i].Tostring();
var t = new Task(() => encryptionFunction(file,destinationPath));
t.Start();
t.Wait();
if (t.isFaulted){
//Display error
}else if(t.isCompleted){
//Display completed message
list.Items.RemoveAt(i);
list.Update();
}
}

I hope this helps someone and saves them the trouble of researching for the problem. If there are any suggestions on how to make it better or another way to solve this, feel free to comment!

Advertisements