Excel Interop Secondary AxisGroup only appearing sometimes - c#

So, I wrote a short little C# program that will take some text files and produce some scatterplots out of them. The plot has 2 series on it and 2 y-axes. For some reason, the second series does not appear on every run. However, it always appears if you step through the program with the debugger.
My code for the 2 series is as follows:
//show records data
Microsoft.Office.Interop.Excel.Series series1b = seriesCollection2.NewSeries();
series1b.AxisGroup = XlAxisGroup.xlPrimary;
series1b.Name = "Records";
series1b.XValues = ws.get_Range("A" + FACT_TABLE_START.ToString() + ":A" + FACT_TABLE_END.ToString());
series1b.Values = ws.get_Range("D" + FACT_TABLE_START.ToString() + ":D" + FACT_TABLE_END.ToString());
System.Threading.Thread.Sleep(500);
//show duration data
Microsoft.Office.Interop.Excel.Series series2b = seriesCollection2.NewSeries();
series2b.AxisGroup = XlAxisGroup.xlSecondary;
series2b.Name = "Duration";
series2b.XValues = ws.get_Range("A" + FACT_TABLE_START.ToString() + ":A" + FACT_TABLE_END.ToString());
series2b.Values = ws.get_Range("E" + FACT_TABLE_START.ToString() + ":E" + FACT_TABLE_END.ToString());
Probably about 3/4 of the time, the second series will appear just fine. But the other 1/4, series2b will not appear on the plot. I am guessing something asynchronous is going on here? I added the Sleep(500) statement because it seemed to make series2b appear more often.
Why are my graphs only sometimes being created properly?

Related

Possible memory leak in simple batch file processing function in c#

I'm running a very simple function that reads lines from a text file in batches. Each line contains an sql query so the function grabs a specified number of queries, executes them against the SQL database, then grabs the next batch of queries until the entire file is read. The problem is that over time with very large files the process starts to slow considerably. I'm guessing there is a memory leak somewhere in the function but can't determine where it may be. There is nothing else going on while this function is running. My programming skills are crude at best so please go easy on me. :)
for (int x = 0; x<= totalBatchesInt; x++)
{
var lines = System.IO.File.ReadLines(file).Skip(skipCount).Take(batchSize).ToArray();
string test = string.Join("\n", lines);
SqlCommand cmd = new SqlCommand(test.ToString());
try
{
var rowsEffected = qm.ExecuteNonQuery(CommandType.Text, cmd.CommandText, 6000, true);
totalRowsEffected = totalRowsEffected + rowsEffected;
globalRecordCounter = globalRecordCounter + rowsEffected;
fileRecordCounter = fileRecordCounter + rowsEffected;
skipCount = skipCount + batchSize;
TraceSource.TraceEvent(TraceEventType.Information, (int)ProcessEvents.Starting, "Rows
progress for " + folderName + "_" + fileName + " : " + fileRecordCounter.ToString() + "
of " + linesCount + " records");
}
catch (Exception esql)
{
TraceSource.TraceEvent(TraceEventType.Information, (int)ProcessEvents.Cancelling, "Error
processing file " + folderName + "_" + fileName + " : " + esql.Message.ToString() + ".
Aborting file read");
}
}
There are many things wrong with your code:
You never dispose your command. That's a native handle to an ODBC driver, waiting for the garbage collector to dispose it is very bad practice.
You shouldn't be sending those commands individually anyway. Either send them all at once in one command, or use transactions to group them together.
This one is the reason why it's getting slower over time: File.ReadLines(file).Skip(skipCount).Take(batchSize) will read the same file over and over and ignore a growing amount of lines every attempt, and so growing slower and slower as the number of lines ignored (but processed) gets larger and larger.
To fix #3, simply create the enumerator once and iterate it in batches. In pure C#, you can do something like:
using var enumerator = File.ReadLines(file).GetEnumerator();
for (int x = 0; x<= totalBatchesInt; x++)
{
var lines = new List<string>();
while(enumerator.MoveNext() && lines.Count < batchSize)
list.Add(enumerator.Current);
string test = string.Join("\n", lines);
// your code...
}
Or if you're using Morelinq (which I recommend), something like this:
foreach(var lines in File.ReadLines(file).Batch(batchSize))
{
// your code...
}

Second for loop isn't running inside my update

This if statement within the update() have 2 for-loop, but it only runs the first one after the if condition is activated, and I don't know why.
I'm building a code for path optimizing in unity. Currently I have to find out the path that came across the nodes/points/positions with a certain positions array that the index is the order the path should follow. Some path between 2 nodes are repeated , ex: A to B and B to A is consider the same path and shall thicken the width of line AB eventually rendered. So I tried to sort out the position array into 2 different array for comparing if any of the pair of nodes(or we can say line) is repeated. And I encountered a problem in if statement within the update().
The first should sort out the original array for later comparison. The second one is just for testing if the first one do their job. No comparing yet. However after hitting play and satisfy the if statement I can see all the Debug.log in the first one, everything is normal, the sorting is normal, while the second one just doesn't print anything at all.
I tried comment out the first one, and the second one will run.
I tried to put second one outside the if statement, after it, and without commenting the first one, the second one won't run.
I tried to put the second one before the first one, in the if statement, the second one will run and the first one won't.
So I think this might be some kind of syntax error or am I using the if statement wrong? Please help.
if (l > 0)//activate when we choose any preset processes
{
for (int n = 0; n <= positions.Length; n++)//this loop will sort all the pos1 and pos 2 into array for current frame
{
curPos_1 = positions[n];//current position of node 1
curPos_2 = positions[n + 1];
Debug.Log("CURPOS_1 of line number " + n + " is " + curPos_1);
Debug.Log("CURPOS_2 of line number " + n + " is " + curPos_2);
flag[n] = 0;
Pos_1[n] = curPos_1;
Pos_2[n] = curPos_2;
Debug.Log("POS_1 array of line number " + n + " is " + Pos_1[n]);
Debug.Log("POS_2 array of line number " + n + " is " + Pos_2[n]);
}
for (int o = 0; o <= positions.Length; o++)
{
Debug.Log("flag of number " + o + " is " + flag[o]);
}
}
As described, all for loop should print something. Not just one of it.
Have you checked your Unity Console Window ?
In your first loop you get the next item but its condition will fail at the end, i.e. off by one.
Correct code should be something like this:
var floats = new float[100];
for (var i = 0; i < floats.Length - 1; i++)
{
var f1 = floats[i];
var f2 = floats[i + 1];
}
Now, Unity, has a behavior of ON ERROR RESUME NEXT, so it's highly probable that an error has occured but you haven't seen it (did you turn off the red icon for toggling errors in console ?).
Also, for some conditions only you know about (you didn't post the whole context), it could work once after you've changed some state of your program.

Problems with EquationMgr & SelectionManger Solidworks Api C#

I'm trying to understand principles of solidworks API, but have several problems.
Here is my code:
for (var i = 0; i < selMgr.GetSelectedObjectCount(); i++)
{
var Face = selMgr.GetSelectedObject(i+1);
surfaces.Add(Face.GetSurface());
measure = swModel.Extension.CreateMeasure();
if (surfaces[i].IsCylinder())
{
// Problem # 1
Console.WriteLine("Cylinder " + i);
measure.Calculate(surfaces[i]);
var diameter = measure.Diameter * 1000;
var length = 1000 * measure.Perimeter / (measure.Diameter * Math.PI);
var temp = swApp.OpenDoc6(#"E:\OAK\Locator9.SLDPRT", 1, 1, "", 0, 0);
var part = component.AddComponent5(#"E:\OAK\Locator9.SLDPRT", 0, "", true, "", 0, 0, 0.3);
swApp.CloseDoc(#"E:\OAK\Locator9.SLDPRT");
ModelDoc2 locator = part.GetModelDoc();
var eqMgr = locator.GetEquationMgr();
Console.WriteLine("Evaluated diameter " + diameter);
Console.WriteLine("Evaluated length " + length);
Console.WriteLine(eqMgr.Equation[1] + " " + eqMgr.Equation[2]);
//Problem #2
eqMgr.set_Equation(1, $#"""D""={diameter}");
eqMgr.set_Equation(2, $#"""L""={length}");
eqMgr.EvaluateAll();
locator.EditRebuild3();
locator.ForceRebuild3(false);
}
else
{
// TODO: Handle other type of surface
}
}
1) I want to measure perimeter & diameter of the selected surface. But if a return value of GetSelectedObjectCount() method is greater than 1, measure.Diameter & measure.Perimeter both returns -1. And I kinda understand why, 'cause such operation isn't possible via UI as well, but can I do smth to solve the problem?
2) The code above has no influence on the equation of the inserted component, even if it writes it on the console.
Help please!
1 For primitive surfaces you can use *Params property of the ISurface object to get the information you need. For cylinder it would be CylinderParams. I can't find the link right now but I remember reading that measure shouldn't be used for any precise calculations as it is not guaranteed to be accurate at all times. If you don't care about precision and still want to use measure you can manually manipulate set of selected objects.
2 I haven't used IEquationMgr but in general I tried to stay away from VB styled parameterized properties like Equation , I'd suggest trying to Delete and then Add equation.

Checking if two strings are the same, if they are, need to redo loop

firstRound = (i + "&" + partnerOne);
secondRound = (i + "&" + partnerTwo);
while (firstRound.Equals(secondRound))
{
myCount = myCount + 1;
spotTwo = rnd.Next(heelerEntries.Count);
partnerTwo = heelerEntriesTwo[spotTwo];
secondRound = (i + "&" + partnerTwo);
if (myCount == 5)
{
MessageBox.Show("Messed up 5 times!");
break;
}
My problem is that sometimes when executing the code, i will end up with the same team "A&G" for round one, and "A&G" for round two. List 1 has ABCDEF and list 2 has GHIJKL. I want it to check the teams from both rounds, and if any are the same, redo the randomizing for the second round.
As seen in the code above, i am trying to see if the strings firstRound and secondRound are the same. If they are, i want it to redo the entire second round loop. The code is for randomizing teams from a list so i cannot have the same team for the different rounds. If anyone is able to help, or give me other ideas on ways to do this, i appreciate it.

Why is my Expression for Array Length Just Returning 1?

I'm working on a game in Unity, and just noticed an odd bug that comes up sometimes. What's happening is that a string array that I'm instantiating is being created too short, even though the log messages I'm writing confirm that the expression should be creating a larger array.
Here's the relevant snippet of code:
Debug.Log("hero.power = " + hero.power.ToString());
Debug.Log("allyPower = " + allyPower.ToString());
Debug.Log("opponent.power = " + opponent.power.ToString());
int max = Mathf.Max(hero.power + allyPower, opponent.power);
report.flips[hero.name] = new string[hero.power + allyPower];
report.flips[opponent.name] = new string[opponent.power];
Debug.Log("max = " + max.ToString());
Debug.Log("report.flips[hero.name].Length = " + report.flips[hero.name].Length.ToString());
And the output this creates in Unity:
This shows that hero.power is 3, and allyPower is 0 but instead of creating a string[3] it creates a string[1].
Is there something about using expressions to determine the length of arrays that's causing an issue here? I temporarily changed to this:
int heroArrayLength = hero.power + allyPower;
report.flips[hero.name] = new string[heroArrayLength];
And it seems to have helped, though the bug was erratic before so I'm not entirely certain it's fixed. And even if it is, I'm still unclear what the actual cause is.
Does anyone know what's happening here?
If hero.name is the same as opponent.name, then:
report.flips[hero.name] = new string[hero.power + allyPower];
report.flips[opponent.name] = new string[opponent.power];
will both be setting the same "flips" (whatever "flips" is/are), and the second time "wins". Since opponent.power is 1, the final array will be of length 1, which means that report.flips[hero.name] will be length 1.

Categories

Resources