Doriak

I got following error in a very basic VSTO Excel Workbook project. My method responds to a hyperlink, sets some integer values in a 10x10 cells array; and then user rng.Find() to find a specific string. However, the last part is when the while loop continues trying to get the next string with rng.FindNext(foundRange). The strings are found, but then Excel does not return from it (it takes all my CPU time); and finally, I got this error.

ContextSwitchDeadlock was detected
Message: The CLR has been unable to transition from COM context 0x159bc0 to COM context 0x1598e0 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.

Some help please to understand this.

thanks,

Doriak



Re: Visual Studio Tools for Office Why does the ContextSwitchDeadlock happens?

Martin Sawicki

Doriak

Any chance you could post the relevant code sample so we could take a look at what exactly you're encountering so we can debug it further

Thanks





Re: Visual Studio Tools for Office Why does the ContextSwitchDeadlock happens?

Geoff Darst

Hi Doriak,

When you are in debug mode, the CLR has some managed debug assistants (MDA's) that run around looking for bugs (or potential bugs in your code).  The ContextSwitchDeadlock MDA behaves like this: a background thread runs that will (every 60 seconds) attempt to enter the STA that your code is running in.  The way STA works is that a message based protocol is used to marshal calls.  So in order for the MDA to enter, the marshalling message must get processed--which requires that a GetMessage or PeekMessage call be executed on the STA thread in that timeframe.

What this MDA message means then, is that your code has either explicitly or implicitly entered a codepath that is preventing control to flow back to Excel's main message loop.  This could be caused by an infinite loop, or just a long operation.  For example, you can trigger this MDA if you try to synchronously communicate with a database & end up blocking while you wait for a long query to complete.

In your case, since the CPU utilization is at 100% it sounds like you've gotten yourself into an infinite loop.  My guess is that you aren't handling your Range.FindNext call correctly to terminate your loop.  Here's what Help says about that method in remarks:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

When the search reaches the end of the specified search range, it wraps around to the beginning of the range. To stop a search when this wraparound occurs, save the address of the first found cell, and then test each successive found-cell address against this saved address.

>>>>>>>>>>>>>>>>>>>>>>>>>>

Could it be that you aren't doing this and therefore that your loop termination condition is always false

Hope that helps.  If you still can't figure this out, feel free to post code as Martin suggested.

Sincerely,

Geoff Darst

Microsoft VSTO Tools

 

 





Re: Visual Studio Tools for Office Why does the ContextSwitchDeadlock happens?

Doriak

Geoff and Martin,

Thanks for your responses on this issue. At least, I understand now, what happened.

As for the first code, I followed your instructions, and checked for the condition. What I found is that by following the example code on "Visual Studio Tools for Office" book from Carter and Lippert (pg. 220) the code enters in an infinite loop. As mentioned by Geoff, a check needs to be done in order to avoid this. Maybe, somebody can double-check the code and see if this statement is right.

However, the ContextSwitchDeadlock is happening now at several places in a particular project I am working on. This happen because the operations take long time , not because of infinite loops.

In one place, I am opening 8 text files, each one with 60,000 lines, and consolidating all the sheets in one workbook. After about 90 seconds, I get the ContextSwithcDeadlock.

foreach (FileInfo fi in fiArray) --> there are 8 files

{

//Increase sheet counter

countSheet++;

Globals.ThisWorkbook.Application.Workbooks.OpenText(

fi.FullName,

Type.Missing,

1, //start row

parsingtype, //delimited

qualifier, //double quote

Type.Missing,

Type.Missing,

Type.Missing,

Type.Missing,

Type.Missing,

other, //character delimiter=true

otherCharacter, //character delimite

limiterArray, //array for delimiters

Type.Missing,

Type.Missing,

Type.Missing,

true, //trailing numbers

Type.Missing);

Excel.Window tempwindow = Globals.ThisWorkbook.Application.Windows.get_Item(fi.Name);

Excel.Worksheet wksheet = tempwindow.Application.Sheets.get_Item(1) as Excel.Worksheet;

//Move the sheet to the next index in the workfile

int index = countSheet;

wksheet.Name = prefix + countSheet.ToString();

wksheet.Move(wb.Sheets[index],Type.Missing); ---> ContextSwitchDeadlock here after 6 files

}

If I hit continue, the process continues and finishes with the workbook complete and with accurate dataq.

At another place, I am using a Find() function to look for in this consolated file for specific cell values. The search logic goes cell by cell on one column in each sheet, looking for the value. Again, after 90 seconds, I get the ContextSwitchDeadlock error. Hit continue, and the operation continues.

//Go through all the sheets in Report

for (int k = 1; k < wbTBR.Sheets.Count; k++) ----> these are 8 sheets, each one with 60000 rows

{

//Set current worksheet in Report

wsTBRCurrent = wbTBR.Sheets[k] as Excel.Worksheet;

//Get the "A" column in Report as a range ---> search value only on column A

rngTBRColumns = wsTBRCurrent.Columns["A", Type.Missing] as Excel.Range;

rngFoundFirst = null;

//FIND THE VALUE in report

rngFound = rngTBRColumns.Find(

rngLookFor.Value2,

Type.Missing,

Excel.XlFindLookIn.xlValues, //Look the values

Excel.XlLookAt.xlWhole, //Look the whole, not just the part

Excel.XlSearchOrder.xlByColumns, //Search by columns

Excel.XlSearchDirection.xlNext, //Direction: Next

false, //CASE SENSITIVE (has to match the value)

Type.Missing,

Type.Missing);

//Continue searching as long as it continues to find matches

while (rngFound != null)

{

if (rngFoundFirst == null)

{

//In the case of the first match store the found range

rngFoundFirst = rngFound;

}

else if (rngFound.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing) ==

(rngFoundFirst.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing)))

{

//Break  if the addresss of the found range matches the address of first found range

break;

}

//If value found, then mark it in RESULTS sheet as FOUND and break

shResults.Range["C" + indexNext.ToString(), Type.Missing].Value2 = "FOUND";

break;

}

}

As you can imagine, this is rather annoying, since my whole goal on this project is to automate a function (= "hit the button, come back tomorrow to see the results"), but this error keeps showing up if the operation takes long.

Please let me know how to address this situation. And also, how would this affect a Release version

 

Thanks for the attention,

Doriak

 





Re: Visual Studio Tools for Office Why does the ContextSwitchDeadlock happens?

Geoff Darst

Hi Doriak,

Since the additional cases you mention are caused by Excel operations taking a long time, there isn't much you can do about this MDA firing.  The problem is really in Excel-they should be pumping messages periodically during long operations. 

The good news is that this MDA isn't particularly serious.  There is no real harm in ignoring it since all it is telling you is that there are periods of time where Excel is going to be unresponsive to COM calls.  If you want to turn it off, there are several ways to do this.  See http://msdn2.microsoft.com/en-us/library/d21c150d(en-US,VS.80).aspx.  You can also simply uncheck the ContextSwitchDeadlock exception under Debug.Exceptions.Managed Debugging Assistants if you just want to ignore the exception in the debugger.

Otherwise, about the only thing you could do to eliminate this MDA from firing would be to adjust your input so that the resulting Excel operation takes less time--i.e. give it smaller text files.  However, there are no guarantees that this approach would always be successful. 

Hope that helps,

Geoff Darst

Microsoft VSTO Tools





Re: Visual Studio Tools for Office Why does the ContextSwitchDeadlock happens?

Doriak

Geoff,

Thank you for the answer. I uncchecked it from the Debugging option, and now my test is running from beginning to end w/o interrruption  - even if it takes over 15 minutes :)

Doriak





Re: Visual Studio Tools for Office Why does the ContextSwitchDeadlock happens?

Jerryk

I'm having the same problem with a long process. Where do you do the unchecking Can't find it.

"You can also simply uncheck the ContextSwitchDeadlock exception under Debug.Exceptions.Managed Debugging Assistants if you just want to ignore the exception in the debugger."

Thanks,

Jerry





Re: Visual Studio Tools for Office Why does the ContextSwitchDeadlock happens?

Jerryk

Sorry, I was looking at the property page instead of the menu ...

/jerry