-1

The function shown below is executed many times before it randomly throws the index out of range exception:

public void AddDataT()
        {
            timeT = SerialPortClass.GetInstance().GetTime();
            if (DateTime.Compare(timeT[0], tempTimeT[499]) < 0)
                return;

            foreach (Series ptSeries in chartT.Series)
            {
                if (ptSeries.Name == "Temperature 1")
                    data = SerialPortClass.GetInstance().GetBuffer(5);
                else if (ptSeries.Name == "Temperature 2")
                    data = SerialPortClass.GetInstance().GetBuffer(6);
                else return;

                indexT = 0;
                foreach (float value in data.Latest())
                {
                    AddNewPoint("Temperature", timeT[indexT], value, ptSeries);
                    tempTimeT[indexT] = timeT[indexT];
                    indexT++;
                }
            }
        }

As shown in the screenshot, the index at the moment of the exception was 499, and the array size is 500. I know I'm iterating through another buffer based on its size, but both the data and time buffers always have 500 elements. Any idea what might be causing the exception? Here is the code for the AddNewPoint function:

        public void AddNewPoint(String chart, DateTime timestamp, float point,
            System.Windows.Forms.DataVisualization.Charting.Series ptSeries)
        {
            if (chart == "Voltage")
                scale = scaleV;
            else if (chart == "Current")
                scale = scaleI;
            else scale = scaleT;
            
            ptSeries.Points.AddXY(timestamp, point);
            double removeBefore = timestamp.AddSeconds((double)(scale) * (-1)).ToOADate();

            while (ptSeries.Points[0].XValue < removeBefore)
            {
                ptSeries.Points.RemoveAt(0);
            }

            if (chart == "Voltage")
            {
                chartV.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
                chartV.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddSeconds(scale).ToOADate();
                chartV.Invalidate();
            }
            else if (chart == "Current")
            {
                chartI.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
                chartI.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddSeconds(scale).ToOADate();
                chartI.Invalidate();
            }
            else
            {
                chartT.ChartAreas[0].AxisX.Minimum = ptSeries.Points[0].XValue;
                chartT.ChartAreas[0].AxisX.Maximum = DateTime.FromOADate(ptSeries.Points[0].XValue).AddSeconds(scale).ToOADate();
                chartT.Invalidate();
            }
        }

Visual Studio Screenshot

This doesn't happen all the time, so I'm considering just using a try statement so that the program can keep running when this exception happens occasionally.

Rod1022
  • 13
  • 5
  • From your image and the line of the exception (don't post images, please), you got an index out of range exception because you reach `indexT >= time.Length` . This happens if `data.Latest()` contains more items than `time`. Or the exception occurs in the `AddNewPoint` method... –  Jan 12 '21 at 03:38
  • @OlivierRogier that's not possible - he has shown us that in the screen shot. The `time.Count` is 500 so it has to have a 499th item. – Jeremy Thompson Jan 12 '21 at 03:42
  • @OlivierRogier look at the picture: https://i.stack.imgur.com/ZeFak.png - far out you're not very helpful... **No it happens on that error NOT in the `AddNewPoint` function.** The OP will see the error if he steps through the code and see's which argument is out of range.. – Jeremy Thompson Jan 12 '21 at 03:47
  • 1
    @JeremyThompson you are correct, this is not an issue with AddNewPoint – Rod1022 Jan 12 '21 at 03:51
  • @Rod1022 You can't get an out of range exception when the index is in range... It's totally impossible. Totally. Never. The problem is elsewhere. So either your image is misleading or the error occurs in AddNewPoint, which it should be, but without code how to know? –  Jan 12 '21 at 03:54
  • @OlivierRogier I see. You could have asked for more information instead of closing my question and preventing other people from suggesting me things... – Rod1022 Jan 12 '21 at 03:59
  • @Rod1022 I haven't closed the question. I don't have that power. I took a look at the problem and voted to close for duplicate, so my comment. You need to edit, update, and fix your question, starting by removing the image and display the code instead, with the AddNewPoint method as well instead of saying it has no problem... So you can get reopens if necessary. –  Jan 12 '21 at 04:04
  • 1
    I added more info (I was worried about showing more code since this is for school), but I don't see the point of removing the image as that is vital to the issue – Rod1022 Jan 12 '21 at 04:10
  • @Rod1022 You should check if collections indexers are within range before accessing them, for `timeT` and `ptSeries.Points` and `chartV.ChartAreas` and `chartI.ChartAreas` and `chartT.ChartAreas`, so the code will be cleaner and you will be able to detect and control errors. Having said that, I suspect that this happens at **`while (ptSeries.Points[0]...) ptSeries.Points.RemoveAt(0);`** (very *dirty* without bounds checking) else later. –  Jan 12 '21 at 04:23
  • @OlivierRogier `ptSeries` will always have a point at index 0 since at that loop the function has already added a point. I was thinking this could be and issue with the time buffer, as I have it add and remove a value every millisecond or so on another thread, so it is possible that I make a copy of that buffer right when it only has 499 elements. However, debugging showed that it did have 500 elements, so that can't be the issue either. When it comes to `ChartAreas`, if it had no element at index 0 then I wouldn't be able to visualize the chart, which I can – Rod1022 Jan 12 '21 at 04:28
  • @Rod1022 What do you expect to get when removed the last element and loop again on `while (ptSeries.Points[0]...) ptSeries.Points.RemoveAt(0);` ? You should try to correct the condition: `while ( ptSeries.Points.Length > 0 && ptSeries.Points[0]...)`. And after the loop, also check: `if ( ptSeries.Points[0] > 0 ) ...` and `if ( chartX.ChartAreas.Length > 0 ) ...` and so on. –  Jan 12 '21 at 04:39
  • @OlivierRogier that is a good suggestion, but I know that Points[] is never empty since they are being displayed on screen. While debugging I noticed that there were 787 points when it threw the exception. Still, it will be useful to have that extra check – Rod1022 Jan 12 '21 at 04:43
  • @Rod1022 "*being displayed on screen*" (or ignoring unwanted exception in such case) is not proof of clean code nor a robust `while`, otherwise you will not get an exception. –  Jan 12 '21 at 04:49
  • Likely the simplest explanation is you have two threads changing `indexT`. Although hard to be sure without a [mcve]. – mjwills Jan 12 '21 at 07:09

1 Answers1

-2

On line 210 put a Conditional Breakpoint.

Set the Condition to indexT >= 499

Now debug your code, if you're not sure how to debug watch some video's, it'll take 10-15mins to learn the most handy features.

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • Downvoter, this is the correct way to debug the problem. Unless its a corrupted solution (delete obj, bin folders and suo file) then the way you solve this is with the debugger. – Jeremy Thompson Jan 12 '21 at 03:41
  • 1
    Thank you for taking the time to share your knowledge & experience. But your answer has a low quality. Sometimes a comment or a flag/close may be more relevant. To help you improve your answersplease read [How do I write a good answer](https://stackoverflow.com/help/how-to-answer), [How do I write a good answer to a question](https://meta.stackexchange.com/questions/7656/how-do-i-write-a-good-answer-to-a-question) & [Answering technical questions helpfully](https://codeblog.jonskeet.uk/2009/02/17/answering-technical-questions-helpfully). –  Jan 12 '21 at 03:44
  • You're giving **WRONG** advice - you had to delete your comment! – Jeremy Thompson Jan 12 '21 at 03:45
  • Not sure why this was flagged as duplicate? I know what an "Index out of Range" exception is, but none of the posts I found in this website deals with an index that is NOT, in fact, out of range. I included the image (why have an image feature if I'm not supposed to use it?) to prove that that was the case... – Rod1022 Jan 12 '21 at 03:49
  • @OlivierRogier you might be right, but that would imply two huge issues with Visual Studio, the most reputable coding platform. 1 is that it displays wrong object values when debugging, and 2 is that it breaks execution at the wrong line of the code – Rod1022 Jan 12 '21 at 03:55
  • @JeremyThompson I understand. This issue could be due to something completely elsewhere in my relatively large project. I just figured the situation was so odd that it had happened to other people who would have a helpful suggestion – Rod1022 Jan 12 '21 at 03:57
  • @Rod1022 if you debug it, and halt on line 210 at `indexT = 499` and hover the mouse over the arguments and test which one is out of range. – Jeremy Thompson Jan 12 '21 at 04:00
  • @JeremyThompson I've been debugging for years and somehow didn't know that conditional breakpoints were a thing, so thanks for that! Unfortunately, this is not very helpful as the exception is not thrown every time the index reaches 499. The function is executed fine many times (dozens) before this issue happens – Rod1022 Jan 12 '21 at 04:05
  • @Rod1022 wrap the `AddNewPoint` in a Try/Catch, put a breakpoint on the `Catch(Exception ex)` and see that way. – Jeremy Thompson Jan 12 '21 at 04:08
  • @JeremyThompson I did this and after a minute of running the code (meaning that the function was executed over 100 times), it stopped at the breakpoint. I checked the index everywhere and it always displayed as 499, while all the arrays had a count of 500. I clicked on "Continue" and the program kept running fine, so I think the solution is to just ignore this exception – Rod1022 Jan 12 '21 at 04:21
  • When it breaks on the break point, did you hover over the arg's to see which one was out of range? My motto is: *Use Exception Handling Exceptionally* - you're better off putting in a explicit [ExcecptionArgumentOutOfRange](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception?view=net-5.0) and tracking down why its happening. then when you work out why remove the Try/Catch. Also check for corruption, close solution - delete bin & obj folders plus the suo file. Now try and reproduce the problem? Was the solution corrupt? – Jeremy Thompson Jan 12 '21 at 04:26