My team and I continually have issues with the CalcManager blowing up when the grid changes due to a sort, group by, or if we leave the form and the grid is disposed but yet the CalcManager continues to run and then blows up when running asynchronously. Such as a user grouping by multiple columns real quick right after each other. We have not been able to produce a sample application because it seems to be somewhat tied to the complexity of our grid with as many columns and rows as it can contain. We've attempted updating versions a couple times over the past few months, however, the issue has not been resolved. I know the stack posted below says 9.1 but we have tried with newer versions as well. It appears that the problem occurs because the CalcManager is attempting to perform operations on a grid reference that doesn't exist because it has been changed but yet the CalcManager was either not informed or began running shortly before a grid change occurred and so now elements are no longer valid. The stack varies slightly from error to error depending on the action which caused the exception but for the most part contains the same information. It is as follows:
StackTrace: at Infragistics.Win.CalcEngine.RefParser..ctor(String refName) at Infragistics.Win.CalcEngine.RefBase.CreateParsedReference() at Infragistics.Win.CalcEngine.RefBase.get_ParsedReference() at Infragistics.Win.UltraWinGrid.UltraGridRefBase.get_ParsedReference() at Infragistics.Win.UltraWinGrid.UltraGridRefBase.ContainsReferenceHelper(IUltraCalcReference inReference, Boolean isProperSubset) at Infragistics.Win.UltraWinGrid.UltraGridRefBase.IsSubsetReference(IUltraCalcReference inReference) at Infragistics.Win.CalcEngine.UltraCalcEngine.FormulasSubsetOf(IUltraCalcReference baseReference, IUltraCalcReferenceCollection referenceCollection) at Infragistics.Win.CalcEngine.UltraCalcEngine.ConnectReferences(IUltraCalcReference reference, Int32 connect) at Infragistics.Win.CalcEngine.UltraCalcEngine.ProcessTopologicalEvent(QueueInfo item) at Infragistics.Win.CalcEngine.UltraCalcEngine.CleanTopologicalEventQueue(Int64 ticks) at Infragistics.Win.CalcEngine.UltraCalcEngine.Recalc(Int64 ticks, Boolean isStartOfRecalcOperation) at Infragistics.Win.CalcEngine.UltraCalcEngine.Recalc(Int64 ticks) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalcInternal(Int64 ticks) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.ReCalc(Int64 millis) at Infragistics.Win.UltraWinCalcManager.UltraCalcManager.onTimerTick(Object sender, EventArgs e) at System.Windows.Forms.Timer.OnTick(EventArgs e) at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
In hope of reaching some type of solution I added the infragistics projects to our project and debugged the issue. I can actually resolve the issue by modifying the infragistics code as follows:
-I made the Infragistics.Win.CalcEngine.QueueInfo a public class and then added the following code at the beginning of the timer tick event:
if(this.calcEngine != null && this.calcEngine.EventQueue != null && this.calcEngine.EventQueue.Count > 0)
{
object[] qi = this.calcEngine.EventQueue.ToArray();
for(int i = 0; i < qi.Length; i++)
{ if ((qi[i] as UltraCalcEngine.QueueInfo).Reference.ElementName == "()")
this.StopTimer();
return;
}
While this does seem to resolve my issues for now I am wary about using a modified control and have not implemented this in our actual application yet. I don't know how looping through this queue will affect performance or other areas. Is this a valid fix? Can this be implemented in some type of patch or hotfix? Is there a way to handle this without modifying the code? Thank you for any input.
I'm also having the same issue. In addition, it certainly does not like you removing or ammending the formula of a column/summary that is currently being calculated asynchronously.
I've tried suspending the CalcManager before grouping, sorting, filtering, removing etc. and resuming it after but it appears to have no affect, as if the CalcManager (as you say, ecarrish) has not been informed of the change or has begun before being informed...
I'd also be very greatful if someone could provide a solution to this.
Cheers,
Richard
Richard, I have yet to find a solution. I've even submitted the issue to infragistics twice with priority support but they have not been able to solve the issue because I cannot provide a sample application. I cannot seem to reproduce the issue in a small scale application and providing my company's code and data is definitely off the table. Are you able to reproduce the issue in a small scaled down application that could be submitted to Infragistics development team? If so please do or post and I will.
I have been able to modify Infragistics code to resolve the issue, however, I don't use this modified solution because I'm afraid of whether or not it might cause other unforeseen issues. But you can check it out my post at http://forums.infragistics.com/forums/p/8378/211014.aspx#211014
Also, because bug after bug has been logged by our users I have started eating the exception. Below is how I'm doing that if you deem this necessary as a last resort.
Modify the Program.cs(or whatever your application start page is that calls Application.Run and place the following code prior to calling Application.Run:
// Add the event handler for handling UI thread exceptions to the event.Application.ThreadException += new ThreadExceptionEventHandler(MainForm.MainForm_UIThreadException);
// Set the unhandled exception mode to force all Windows Forms errors to go through// our handler.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Then add the above declared event handler to your main windows form:
/// <summary>/// Handles the UIThreadException event of the MainForm control./// Meant to bypass the //"Invalid reference //mainUltraGrid/Table/(). Empty element encountered at location 22." /// CalcManager Exception/// </summary>/// <param name="sender">The source of the event.</param>/// <param name="t">The <see cref="System.Threading.ThreadExceptionEventArgs"/> instance containing the event data.</param>public static void MainForm_UIThreadException(object sender, ThreadExceptionEventArgs t){ if (!(t.Exception != null && (t.Exception is Infragistics.Win.CalcEngine.UltraCalcException || t.Exception.ToString().ToLower().Contains("ultracalcmanager.ontimertick")))) { FormUtilities.DisplayExceptionMessageBox(t.Exception, true); Application.Exit(); }}
Also, be sure to remove the eventhandler on exit. I've read it could cause memory issues otherwise.
Again, that isn't what I'd prefer to be doing but it beats the heck out of the users constantly logging bugs for the same thing.
Thanks for your solution, it appears to me like a threading issue with the CalcManager. EIther we're not using it correctly or it's a bug. I've established it's easier to reproduce if defered calculations is off and it is asynchronous. Then if you group by several columns, have a load of formula columns and summaries to slow down the grid, it appears to be more frequent.
I'm afraid I'm in a simillar situation to you in that I don't really have the time to sort out a sample application right now. Instead, I have a temporary fix of my own (again not the most ideal but it may provide a bit more confidence in that it shouldn't influence anything else).
What I've done is to have a seperate grid and datatable in memory (aside from the grid and datatable visible to the user). The one visible to the user has bound columns for the regular data (i.e. they're added in the datatable and committed to the grid), but any columns with formulas are unbound (i.e. they're simply added to the grid so should not appear in the underlying datasource). This appears to solve the issue of removing and editing formula columns and any other issue regarding grouping, sorting etc. You'll probably find it hangs when attempting to sort or group on a formula column, but that's simply because it has to recalculate all the values in the column before it can sort it (i presume).
The grid and datatable in memory are both created and modified on a seperate. The difference bettween this and the visible gird is that all the columns are bound (including the formula columns). Every time a formula is added, removed or modified (or data is updated), this table is recreated and the grid used to recalculate the values manually.
It's not an amazing solution i guess as it obviously provides a bit of a performance hit when generating the table, but it's reasonable for test data of around 10,000 rows. By the way, unless you need the DataTable source to hold the formula values, you don't need the memory grid and datatable, just making the columns unbound should do the trick (sorry, I presume your columns are all bound?).
I've also noticed it helps to suspend and resume the CalcManager before doing any modification, adding, removing of formulas in the grid.
Apologies if this is all a bit wordy, I'm slightly typing as I think sort of thing...hope that helps anyways. Fire away if you need me to clarify anything.