none
Uptime issues with Build 17763

    Question

  • I have a product that uses build 17763 on Raspberry PI 3.  Although the application is well debugged, and the config.txt file is properly configured...including keeping the GPU at 250 Mhz...after several months of uptime testing, we just can't get the device to stay fully operable for longer than a week without issues.  The core of the system stays running, but we either see an application restart every couple of days randomly (like a framework failure) or a failure of the standard video driver when being used with the official RP touch screen through the dedicated port.  We have a hardware based watchdog on our product should a lockup occur, but this watchdog never fires because the application is still running despite the other issues.  Also the onboard sound card had to be disabled to make sure it does not crash the digitizer driver for the touch screen.  Has anyone at Microsoft seen these issues in longer term testing because after several months, my company can't find design issues in our application code?  We also don't see issues with the power supply or hardware as it was designed into the product and we monitor the power supply output during testing...if we can't work this out we might have to switch up hardware and see if different drivers make a difference...

    Thank you,


    Dan DeMerchant


    • Edited by danoplus Thursday, November 22, 2018 9:27 PM
    Thursday, November 22, 2018 9:26 PM

All replies

  • Hello danoplus,

    >>>I have a product that uses build 17763 on Raspberry PI 3.

    Which version do you use 17763.1 or 17763.107?

    >>>The core of the system stays running, but we either see an application restart every couple of days randomly (like a framework failure) 

    Do you mean your app restart by itself but the system doesn't restart? If the system always running you can get the live process dump of the app via device portal.

    In general, the app won't restart automatically except you design it to be, but on Windows IoT Core the background application will auto restart. So are you talking about background application?

    >>>Has anyone at Microsoft seen these issues in longer term testing because after several months, my company can't find design issues in our application code?

    I never see this issue that app restart after long time running. Maybe I didn't run long enough or apps I used can't reproduce this issue. And I never heard of this issue. 

    If possible, you can run your app on other device like Windows 10 desktop to see if it can reproduce this issue.

    As for touch screen freeze issue, it is an known issue when using the 3.5mm Audio/Video Jack on Raspberry Pi 3. Related thread.

    At last, do you use default image or build your custom image?

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 23, 2018 6:12 AM
    Moderator
  • Version is 17763.1.  Wasn't aware of a 17763.107...dashboard does not show more information than the base build number.  Any release notes on *.107 available?

    Yes once in a great while, the app will restart by itself, showing a splash screen without a full reboot of Windows.  We combed through the code for a very long time trying to find a culprit, and even disabled all Dispatch timers to prevent events from occurring during testing and still happens.  This is a foreground application showing on the official touch screen.

    I don't know how the process dump thing works...so I can't seem to get you data on that.  If this is a defaulted feature that is turned on, I definitely can hunt for logs on my test unit as it happens every couple of days.  I am running UWF so hopefully areas that allow this process dump to work are excluded...how does this trace work?

    I can try and re-compile the app and run on a regular desktop machine but without custom SPI-based hardware available it won't do anything and might be difficult to put new conditionals in the code just to do this...I will see what can be done. We are not 100% sure if it's an app issue or not, but there has been 14 months of daily debugging on this app.  The app communicates back and forth via SPI to a STM32F0 microcontroller which acts as a co-processor in the product.

    The touch screen freeze issue when audio is playing has nothing to do with the physical jack FYI...its something with the on-board sound chip hardware on the PI3.  It's not even a complete freeze, it's the screen digitizer failing to operate, which causes the keyboard to lock up in an unrecoverable manner, after playing sounds using the on-board sound chip output (FT5406 driver conflict?).  When the keyboard locks up, it gets stuck on screen with the last key press highlighted, but the app continues to run and respond.  The new keyboard in build 17763.1 has sound enabled by default...when you click a key...and audible click plays.  I had to add a registry entry to change the keyboard so that it does not make the key click.  This resolved the issue completely where the screen touch digitizer driver crashes after several rapid key clicks.  I went a step further because the onboard sound chip can cause this lockup if your app plays a media object...by shutting off the on-board sound driver...used devcon to do this.  This problem does not occur at all if using a USB based sound dongle or device, so we require our customers to use a USB sound device if they want to use the speech features in our product.  It was quite embarrassing because we had a large customer we were demoing the product to last month and the newer build had this keyboard issue that the older one didn't and the keyboard crashed during the demo...had to power cycle to recover... and this put a lot of question marks into the customer's head at that point.  We are still working on getting that account back to the table and it's looking positive.

    This is a default image 17763.1.  Damned if I tried, but can't seem to find all of the stuff needed to build a custom image...and had to ship the product...still working on getting a custom FFU built.  Considered flying in from the East coast (I live in Connecticut) to one of those Microsoft IOT workshops to see if someone could help me with this, but it's low on the priorities list because we have been fighting product bugs with customer service for the last 8 months with the introduction of the product...some of which was our code and some seems not to be.

    With the new keyboard in 11763.1, I also found out that if the product operated for several days the keyboard might not come up when a text box receives focus...unless you set Globalization settings in every frame of code on initialization.  Once I added this line of code to each screen of my application, the problem with the keyboard not popping up went away completely: Windows.Globalization.Language.TrySetInputMethodLanguageTag("en-US");

    Last known issue that I am working on is that the screen itself...(FTSC5406 display driver?) after a week or so of the display operating with the app running...the display could randomly desync...display shows as complete signal loss...even though the foreground app is still ticking away just fine.  I know this because the app is responding to events on the GPIO and SPI perfectly.  In this error mode, the display sits there with no signal and kind of shows white noise signals similar to what happens when you reboot the PI remotely.  This condition is unrecoverable, the user has to reboot the system in order to get the display working again which kind of makes for a very bad user experience.  It's weird because the rest of the system is working perfectly in this condition...I added a line in the config.txt file of the PI to prevent the PI from throttling into turbo mode to see if I can keep hardware timings more stable in order to see if this has an affect on this issue.

    The product is a control panel that monitors the status of eight (building) doors and also handles data coming off of 8 access card readers, one at each door.  There is software that manages it remotely via TCPIP.  It works pretty well when closed up in a control cabinet despite the screen issues and occasional application restart.  I was thinking about adding a reset button to the next hardware revision of this product just as a workaround until I can figure out better hardware to run our application on that fits the economic bill.  We worked around application restarts by queueing data in the co-processor for now until the issue can be found.

    We continue to work on uptime with this particular hardware and it's coming along despite being an uphill battle.

    Thank you.



    Dan DeMerchant

















    • Edited by danoplus Friday, November 23, 2018 7:36 AM
    Friday, November 23, 2018 7:11 AM
  • Hello danoplus,

    >>>Version is 17763.1.  Wasn't aware of a 17763.107...dashboard does not show more information than the base build number.  Any release notes on *.107 available?

    Yes, dashboard not show .107 but 17763.107 is available to download.

    >>>I don't know how the process dump thing works...so I can't seem to get you data on that. .....

    This is a default image 17763.1.

    If you use default image you can use device portal and get live process dump like this:

    Find your app and click "save" button then you will get the dump file saved on your development machine. You can share it or send it to MSDNFSF@microsoft.com with this thread link.

    >>>Damned if I tried, but can't seem to find all of the stuff needed to build a custom image...and had to ship the product...still working on getting a custom FFU built.

    For custom image, you can follow "Get the tools needed to customize Windows IoT Core" and "Lab 1a: Create a basic image". If there is any issue when creating image you can post a new question so we can continue there.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 23, 2018 9:56 AM
    Moderator
  • I did two things that seemed to really fix uptime issues...so far after several days no more random application restarts or screen video loss.  Still testing multiple units but its looking good.  What was done:

    1. Added "DISABLE_AUTO_TURBO=1" to RP3's config.txt.

    2. Upgraded my distribution to 17763.107 from 17763.1.  Not sure if this helped or not.

    Other changes made in config.txt:

    gpu_mem=64 
    core_freq=250               # Frequency of GPU processor core in MHz

    For the record, changes made to the system:

    *** Set Keyboard Height set OskRootKey "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\IoTShellExtension\OSK" cd $OskRootKey Set-ItemProperty -Path . -Name MaxHeightPercentage -Type String -Value 55 *** Turn of keyboard audible click as it causes issues with native PI adapter and setup keyboard settings set OskRootKey "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\IoTShellExtension\OSK" cd $OskRootKey mkdir Preferences cd Preferences Set-ItemProperty . -Name AudioFeedback_Disabled -Value "1" Set-ItemProperty . -Name Paste_Disabled -Value "1"
    *** Disable onboard sound driver
    devcon /r disable root\rpiwav

    -System also uses UWF. Update service disabled.



    Dan DeMerchant


    • Edited by danoplus Wednesday, November 28, 2018 8:27 AM
    Wednesday, November 28, 2018 8:21 AM
  • Hello danoplus,

    Thanks for information.

    It is strange that app will auto restart without trigger your watchdog. I seem found the similar issue of default app on my Raspberry Pi 3 with Windows IoT Core 17763.1 and I did nothing with the default app. I am not sure because I don't see the splash screen but only see the screen turns black and the default app appears again.

    Although you edit some settings get the app more reliable but I suspect the real problem has been solve or not.

    For "auto restart" issue I am contacting with related engineer and update here if there is any progress. I am also doing some test.


    BTW, do you set your app as startup app?

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, November 29, 2018 9:09 AM
    Moderator
  • Yes, my app is set as the startup app.  This morning after four days of run time, my app restarted itself...showing the splash screen.  This must be some type of framework issue...and could be a potential huge problem especially for customers that are doing mission critical stuff...like robotics and the like.  I guess if it was mission critical though you would not be using a PI as the core?  This is on build 17763.107.

    I have disabled our hardware watchdog on the test setup so I know that it's not the cause.  My app does use SPI and storage pretty often but doesn't do much when it's idle.

    Thanks for continuing to look at this because it's still happening…


    Dan DeMerchant




    • Edited by danoplus Thursday, November 29, 2018 1:39 PM
    Thursday, November 29, 2018 1:36 PM
  • We have almost perfect stability with build 16299.125 running a unified write filter. With builds 15063 and 14393 I saw similar issues with the app auto restarting as you have described. So I am not planning on updating our product any time soon. Also the UWF helped with instability, frequent power cycles would almost certainly cause SD Card corruption and app instability. We also found dips on the 5v supply can also cause major instability. We now run our units at 5.25-5.35v to avoid power issues.

    Thursday, November 29, 2018 6:14 PM
  • Unfortunately we saw the application reboot occur on 16299 also...my app might be using part of the framework that yours doesn't perhaps.  If your setup is stable, that is the best thing you can do to hold tight.  I am not sure if the ability for MS to automatically push updates to a device is necessarily helpful...it's not like a PC.  I have been running the power supply on our board at 5.3V...which is what we found we needed to do in order to prevent the PI from complaining about low power conditions.  The supply on our unit is built onto the product and specifically made for the application.  I really think that there is a small framework bug that is causing the application to restart every once in a while...

    Dan DeMerchant

    Thursday, November 29, 2018 10:39 PM
  • Hello danoplus,

    There are two suggestions you can also try:

    • Don't set your app as startup so that it will simple stops instead of restarts then you will get a live dump file when the app stops. You may later to debug and find the exception information.
    • Your app can run a few days then restart/crash, this seems memory leak related. So you can monitor memory usage via device portal to see if it increase overtime. As you have found that increase GPU memory to 64 the app become more stable.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 30, 2018 3:23 AM
    Moderator
  • There is a slow memory leak...!!! Yikes.  Going to work on this.


    • Edited by danoplus Friday, November 30, 2018 7:31 PM
    Friday, November 30, 2018 4:24 AM
  • Hello danoplus,

    Glad to hear you found the real problem.

    There are some suggestions from our related engineers I want to share with you, it maybe helpful for you to debug and find the useful information in future:

    1. You can try is to look in c:ProgramData\Microsoft\Windows\WER\ReportArchive and see if it contains any clues.  Sometimes that can be helpful.
    2. You can run this command “REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SQMClient /v MachineId” and provide us with the GUID that’s returned.  We could try looking up your device to see if it has reported any error events.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Monday, December 3, 2018 1:34 AM
    Moderator
  • I can't actually confirm this yet...but memory seems to be accumulating slowly.  I can't seem to find anything wrong with the code although I have been poking around.  The information you sent over is helpful, but I am not familiar with any of this...

    Dan DeMerchant

    Monday, December 3, 2018 8:22 AM
  • Rita,

    I have tracked down a routine that causes excessive memory accumulation...it's a routine that checks a file that has door unlocking schedule information in it.  I had a timer running that opens the file, checks to see if a particular door should be unlocked, and then unlocks the door if the schedule is active.  This timer was disabled during the time that the schedule calculations were occurring, but happened once every second between checks.  I was able to change this process to only check the schedule at the top of each minute (once per minute firing rate instead of up to 60 times a minute) and it seems to be helping prevent excessive memory accumulation.  My app is still accumulating memory...which concerns my but doing it very slowly.  I don't understand why this memory issue would occur using a StreamReader when the StreamReader is enclosed with a Using command...Using is supposed to call Dispose, but that does not seem to be happening?  I tried manually disposing and also using StreamReader.DiscardBufferData before exiting my Using section but this didn't help.  I am still not convinced that extending the scan time of the schedule is the ultimate solution but it's definitely delaying the memory accumulation issue.  The GC seems to fire much less.  I though .NET was supposed to spoon feed us with automatic garbage collection? :) I REMed out all other timers...and the other processes don't seem to be added to memory accumulation...any idea what I could be missing here?

    Thank you,


    Dan DeMerchant




    • Edited by danoplus Monday, December 3, 2018 10:56 PM
    Monday, December 3, 2018 10:50 PM
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SQMClient
        MachineId    REG_SZ    6118a234-a294-4957-ab2e-f199fdb3ab75


    Dan DeMerchant

    Monday, December 3, 2018 10:54 PM
  • Nothing in ReportArchive...

    Dan DeMerchant

    Monday, December 3, 2018 10:55 PM
  • The offending code:

      public bool ScheduleCheck(string reader_number, string schedule_number)
            {
                try
                {
                    if (schedule_number == "000") { return true; }
                    int day_of_week_number = (int)App.deviceDateTime.DayOfWeek;
                    //see if the controller is in a holiday
                    if (RecurringHolidayCheck() == true) { day_of_week_number = 7; }
                    if (NonRecurringHolidayCheck() == true) { day_of_week_number = 7; }
                    StorageFolder folder = ActiveDataFolder();
                    string bank = ReturnActiveBank();
                    string filename = "schedule" + "_" + reader_number + "_" + day_of_week_number + "_" + bank + ".dat";
                    if (File.Exists(Path.Combine(folder.Path, filename)) == false) return false;
                    using (StreamReader reader = File.OpenText(Path.Combine(folder.Path, filename)))
                    {
                        string[] record=null;
                        while (reader.Peek() >= 0)//foreach (var line in readFile)
                        {
                            string line = reader.ReadLine();
                            record = line.Split('|');
                            if (record[0] == schedule_number)
                            {
                                //if the record is present see if the schedule times fall between the current times
                                string start_time = record[1];
                                start_time = start_time.Insert(2, ":");
                                string end_time = record[2];
                                end_time = end_time.Insert(2, ":");
                                DateTime start = DateTime.Parse(start_time);
                                DateTime end = DateTime.Parse(end_time);
    
                                //use a generic date before comparing the datetimes
                                DateTime currentDateTime = App.deviceDateTime;
                                currentDateTime = new DateTime(2018, 1, 1, currentDateTime.Hour, currentDateTime.Minute, currentDateTime.Second);
                                start = new DateTime(2018, 1, 1, start.Hour, start.Minute, start.Second);
                                end = new DateTime(2018, 1, 1, end.Hour, end.Minute, end.Second);
    
                                if ((currentDateTime >= start) && (currentDateTime < end))
                                { reader.DiscardBufferedData(); return true; }
                                else
                                {//the schedule is not active
                                    reader.DiscardBufferedData(); return false;
                                }
                            }
                        }
                        reader.DiscardBufferedData();
                    }
                    return false;
                }
                catch { return false; }
            }


    Dan DeMerchant

    Tuesday, December 4, 2018 12:07 AM
  • Hello danoplus,

    From the code you have shown, it seems no memory leak because all use of the object are contained within the using statement's code block (within the curly braces { }) and will be released after the block ends.

    >>>I tried manually disposing and also using StreamReader.DiscardBufferData before exiting my Using section but this didn't help.

    So it seems memory leak not caused by StreamReader if you called reader.Dispose().

    How do call ScheduleCheck method? If you use System.Threading.Timer the callback should be static method by default.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, December 4, 2018 8:31 AM
    Moderator
  • Thank you for your continued help with this.  This is one of the only really nested routines in my application.  This is the mechanism:

    public static DispatcherTimer unlockScheduleTimer = new DispatcherTimer(); //declared in App

    In MAINPAGE:

     App.unlockScheduleTimer.Interval = new TimeSpan(0, 0, 0, 1, 0); //unlock schedule timer - uses storage
     App.unlockScheduleTimer.Tick += UnlockTimerTick;
     LastMinute = App.deviceDateTime.Minute; //initialization (declared in main as int)
     App.unlockScheduleTimer.Start();

    private void UnlockTimerTick(object sender, object e)

    { App.unlock_schedule_event_occurring = true; //unlock schedule service try { if (App.prevent_schedule_check == false) { if (LastMinute != App.deviceDateTime.Minute) //fire the check at the top of the minute { AutomaticUnlockScheduleService(); LastMinute = App.deviceDateTime.Minute; } } } catch { } finally { App.unlock_schedule_event_occurring = false; } }


     private void AutomaticUnlockScheduleService()
            {
                try
                {
                    for (byte reader_number = 0; reader_number <= 7; reader_number++)
                    { 
                    StorageHandler sh = new StorageHandler();
                    if (sh.LinkedScheduleCheck(Convert.ToString(reader_number), App.reader_unlock_schedule[reader_number]))
                    {
                        // the schedule is active, unlock the door
                        if (unlock_schedule[reader_number] == false)
                        {
    
                            if (sh.LoadParameter("first_person_in_door_" + reader_number) == "0")
                            { //first person in feature is off
                                unlock_schedule[reader_number] = true;
                                UpdateRelayOutput(reader_number);
                                first_person_in_card_swiped[reader_number] = false;
                                if (sh.LoadParameter("log_door_schedule_events") == "1") Log(Convert.ToString(reader_number), "", "5", "Unlocked by schedule door " + Convert.ToString(reader_number + 1), "pass");
                            }
                            else
                            { //first person in feature is on
                                if (first_person_in_card_swiped[reader_number] == true)
                                {
                                    unlock_schedule[reader_number] = true;
                                    UpdateRelayOutput(reader_number);
                                    first_person_in_card_swiped[reader_number] = false;
                                    if (sh.LoadParameter("log_door_schedule_events") == "1") Log(Convert.ToString(reader_number), "", "5", "Unlocked by schedule door " + Convert.ToString(reader_number + 1), "pass");
                                }
                            }
                        }
                    }
                    else
                    {   //the schedule is not active
                        first_person_in_card_swiped[reader_number] = false;
                        if (unlock_schedule[reader_number] == true)
                        {
                            unlock_schedule[reader_number] = false;
                            UpdateRelayOutput(reader_number);
                            if (sh.LoadParameter("log_door_schedule_events") == "1") Log(Convert.ToString(reader_number), "", "6", "Locked by schedule door " + Convert.ToString(reader_number + 1), "pass");
                        }
                    }
                    }
                }
                catch { }
            }
    The following routines are in a class called "StorageHandler" that I use to keep all routines that do storage.  Some of these routines call each other.  This particular function has a ton of nested calls which might be causing the issue...
     public bool LinkedScheduleCheck(string reader_number, string schedule_number)
            {
                try
                {
                    int number_of_lookups = 0;
                    while (number_of_lookups < NumberOfLinkedSchedulesAllowed)
                    {
                        if (ScheduleCheck(reader_number, schedule_number)) { return true; }
                        string linked_schedule = FindScheduleLinkActiveBank(reader_number, schedule_number);
                        if (linked_schedule != "000")
                        {
                            //there is a linked schedule
                            schedule_number = linked_schedule;
                            number_of_lookups++;
                        }
                        else return false;
                    }
                    return false;
                }
                catch { return false; }
            }

     public bool ScheduleCheck(string reader_number, string schedule_number)
            {
                try
                {
                    if (schedule_number == "000") { return true; }
                    int day_of_week_number = (int)App.deviceDateTime.DayOfWeek;
                    //see if the controller is in a holiday
                    if (RecurringHolidayCheck() == true) { day_of_week_number = 7; }
                    if (NonRecurringHolidayCheck() == true) { day_of_week_number = 7; }
                    StorageFolder folder = ActiveDataFolder();
                    string bank = ReturnActiveBank();
                    string filename = "schedule" + "_" + reader_number + "_" + day_of_week_number + "_" + bank + ".dat";
                    if (File.Exists(Path.Combine(folder.Path, filename)) == false) return false;
                    using (StreamReader reader = File.OpenText(Path.Combine(folder.Path, filename)))
                    {
                        string[] record=null;
                        while (reader.Peek() >= 0)//foreach (var line in readFile)
                        {
                            string line = reader.ReadLine();
                            record = line.Split('|');
                            if (record[0] == schedule_number)
                            {
                                //if the record is present see if the schedule times fall between the current times
                                string start_time = record[1];
                                start_time = start_time.Insert(2, ":");
                                string end_time = record[2];
                                end_time = end_time.Insert(2, ":");
                                DateTime start = DateTime.Parse(start_time);
                                DateTime end = DateTime.Parse(end_time);
    
                                //use a generic date before comparing the datetimes
                                DateTime currentDateTime = App.deviceDateTime;
                                currentDateTime = new DateTime(2018, 1, 1, currentDateTime.Hour, currentDateTime.Minute, currentDateTime.Second);
                                start = new DateTime(2018, 1, 1, start.Hour, start.Minute, start.Second);
                                end = new DateTime(2018, 1, 1, end.Hour, end.Minute, end.Second);
    
                                if ((currentDateTime >= start) && (currentDateTime < end))
                                { reader.DiscardBufferedData(); return true; }
                                else
                                {//the schedule is not active
                                    reader.DiscardBufferedData(); return false;
                                }
                            }
                        }
                        reader.DiscardBufferedData();
                    }
                    return false;
                }
                catch { return false; }
            }

     public string FindScheduleLinkActiveBank(string reader_number, string schedule_number)
            {
                try
                {
                    string filename = "scheduleLink" + "_" + reader_number + "_" + ReturnActiveBank() + ".dat";
                    if (File.Exists(Path.Combine(ActiveDataFolder().Path, filename)) == false) return "000";
                    using (StreamReader reader = File.OpenText(Path.Combine(ActiveDataFolder().Path, filename)))
                    {
                        while (reader.Peek() >= 0)
                        {
                            string[] record = reader.ReadLine().Split('|');
                            if (record[0] == schedule_number) { reader.DiscardBufferedData(); return record[1]; }
                        }
                        reader.DiscardBufferedData();
                    }
                    return "000";
                }
                catch (FileNotFoundException) { return "000"; }
                catch { return "000"; }
                finally { }
            }
    Thank you


    Dan DeMerchant




    • Edited by danoplus Tuesday, December 4, 2018 3:30 PM
    Tuesday, December 4, 2018 3:27 PM
  • Missing a few pieces to this puzzle. Your StorageHandler class is of particular interest.

    Can you include the following code-

    • Class definition for StorageHandler
    • Function definition of Log
    • Function definition of RecurringHolidayCheck
    • Function definition of NonRecurringHolidayCheck
    • Function definition of ActiveDataFolder
    • Function definition of ReturnActiveBank
    • Function definition of UpdateRelayOutput

    //Suggestion Edit

    To rule out your StorageHandler Class try looping that section of code a few extra thousand times to see if the memory leak becomes more pronounced.

    //Add another loop

    ++ for (int x = 0; x < 9999; x++)

    ++{

    for (byte reader_number = 0; reader_number <= 7; reader_number++) {

    }

    ++}

    //

    • Edited by Andy12986 Tuesday, December 4, 2018 11:24 PM Added Suggestion
    Tuesday, December 4, 2018 11:11 PM
  • StorageHander is 5000 lines of code with dozens routines just for storing and retrieving pieces of data off of storage...can't post all of that obviously.

    Memory accumulation occurs even when LOG is not occurring.  Log is the input of a queue:

    void Log(string doorNumber, string ID, string logType, string screenText, string state)
            {
                LogObject entry = new LogObject();
                entry.door_number = doorNumber;
                entry.id = ID;
                entry.log_type = logType;
                entry.screen_log_text = "[" + Convert.ToString(App.deviceDateTime/*DateTime.Now2*/) + "] " + screenText;
                entry.state = state;
                App.logQueue.Enqueue(entry);
                App.logEventTimer.Start();
            }

     public bool RecurringHolidayCheck()
            {
                try
                {
                    StorageFolder folder = ActiveDataFolder();
                    string bank = ReturnActiveBank();
                    string filename = "recurringHoliday" + "_" + bank + ".dat";
                    if (File.Exists(Path.Combine(folder.Path, filename)) == false) return false;
                    string[] record;
                    int startYear, startMonth, startDate, startHour, startMinute;
                    int endYear, endMonth, endDate, endHour, endMinute;
                    DateTime startDateTime, endDateTime;
                    using (StreamReader reader = File.OpenText(Path.Combine(folder.Path, filename)))
                    {
                        while (reader.Peek() >= 0)//foreach (var line in readFile)
                        {
                            string line = reader.ReadLine();
                            //look through the recurring holiday file and see if we are in a recurring holiday this year
                            record = line.Split('|');
                            startYear = App.deviceDateTime.Year; //DateTime.Now2.Year;
                            startMonth = Convert.ToInt16(record[1].Substring(0, 2));
                            startDate = Convert.ToInt16(record[1].Substring(2, 2));
                            startHour = Convert.ToInt16(record[1].Substring(4, 2));
                            startMinute = Convert.ToInt16(record[1].Substring(6, 2));
                            endYear = App.deviceDateTime.Year;// DateTime.Now2.Year;
                            endMonth = Convert.ToInt16(record[1].Substring(8, 2));
                            endDate = Convert.ToInt16(record[1].Substring(10, 2));
                            endHour = Convert.ToInt16(record[1].Substring(12, 2));
                            endMinute = Convert.ToInt16(record[1].Substring(14, 2));
                            startDateTime = new DateTime(startYear, startMonth, startDate, startHour, startMinute, 0);
                            endDateTime = new DateTime(endYear, endMonth, endDate, endHour, endMinute, 0);
                            if ((App.deviceDateTime/*DateTime.Now2*/ >= startDateTime) && (App.deviceDateTime/*DateTime.Now2*/ < endDateTime)) { return true; }
                        }
                    }
                    return false;
                }
                catch (Exception)
                { return false; }
    
                finally { }
            }
            public bool NonRecurringHolidayCheck()
            {
                try
                {
                    StorageFolder folder = ActiveDataFolder();
                    string[] record;
                    string bank = ReturnActiveBank();
                    string filename = "nonRecurringHoliday" + "_" + bank + ".dat";
                    if (File.Exists(Path.Combine(folder.Path, filename)) == false) return false;
                    var file = folder.OpenStreamForReadAsync(filename);
                    int startYear, startMonth, startDate, startHour, startMinute;
                    int endYear, endMonth, endDate, endHour, endMinute;
                    DateTime startDateTime, endDateTime;
                    using (StreamReader reader = File.OpenText(Path.Combine(folder.Path, filename)))//new StreamReader(file))
                    {
                        while (reader.Peek() >= 0)
                        {
                            //look through the recurring holiday file and see if we are in a recurring holiday this year
                            string line = reader.ReadLine();
                            record = line.Split('|');
                            startYear = Convert.ToInt16(record[1].Substring(4, 4));
                            startMonth = Convert.ToInt16(record[1].Substring(0, 2));
                            startDate = Convert.ToInt16(record[1].Substring(2, 2));
                            startHour = Convert.ToInt16(record[1].Substring(8, 2));
                            startMinute = Convert.ToInt16(record[1].Substring(10, 2));
                            endYear = Convert.ToInt16(record[1].Substring(16, 4));
                            endMonth = Convert.ToInt16(record[1].Substring(12, 2));
                            endDate = Convert.ToInt16(record[1].Substring(14, 2));
                            endHour = Convert.ToInt16(record[1].Substring(20, 2));
                            endMinute = Convert.ToInt16(record[1].Substring(22, 2));
                            startDateTime = new DateTime(startYear, startMonth, startDate, startHour, startMinute, 0);
                            endDateTime = new DateTime(endYear, endMonth, endDate, endHour, endMinute, 0);
                            if ((App.deviceDateTime/*DateTime.Now2*/ >= startDateTime) && (App.deviceDateTime/*DateTime.Now2*/ < endDateTime)) { return true; }
                        }
                    }
                    return false;
                }
                catch (Exception)
                {
                    return false;
                }
                finally { }
            }
    public Windows.Storage.StorageFolder ActiveDataFolder()
            {
             return ApplicationData.Current.LocalFolder;
            }
     public string ReturnActiveBank()
            {
                string bank = Convert.ToString(LoadParameter("current_memory_bank"));
                if (bank == "") { return "0"; } else { return bank; }
            }
     void UpdateRelayOutput(byte relay_number)
            {
                //DEBUGGING if (relay_number == 1) { activityText.Text = Convert.ToString(relay_number) + " " + Convert.ToString(access_granted[relay_number]) + Convert.ToString(App.passage[relay_number]) + Convert.ToString(unlock_schedule[relay_number]) + Convert.ToString(unlock_scheduleTouchScreen [relay_number]) + Convert.ToString(App.lockdown [relay_number]) + sh.LoadParameter("first_person_in_door_" + relay_number); }
                //relay state service
                if ((access_granted[relay_number] == true || App.passage[relay_number] == true || unlock_schedule[relay_number] == true || unlock_scheduleTouchScreen[relay_number]) && App.lockdown[relay_number] == false)
                {   //relay on
                    if (App.relay_status[relay_number] == false)
                    {
                        SPI.relay_on(relay_number);
                        App.relay_status[relay_number] = true;
                        //save the values in the case of a reboot
                        //if (access_granted[relay_number] == true) sh.SaveParameter("access_granted_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("access_granted_" + Convert.ToString(relay_number), "0");
                        StorageHandler sh = new StorageHandler();
                        if (App.passage[relay_number] == true) sh.SaveParameter("passage_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("passage_" + Convert.ToString(relay_number), "0");
                        if (unlock_schedule[relay_number] == true) sh.SaveParameter("unlock_schedule_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("unlock_schedule_" + Convert.ToString(relay_number), "0");
                        if (unlock_scheduleTouchScreen[relay_number] == true) sh.SaveParameter("unlock_scheduleTS_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("unlock_scheduleTS_" + Convert.ToString(relay_number), "0");
                        if (App.lockdown[relay_number] == true) sh.SaveParameter("lockdown_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("lockdown_" + Convert.ToString(relay_number), "0");
                    }
                }
                else
                {   //relay off
                    if (App.relay_status[relay_number] == true)
                    {
                        SPI.relay_off(relay_number);
                        App.relay_status[relay_number] = false;
                        dps_opened[relay_number] = false;
                        //save the values in the case of a reboot
                        //if (access_granted[relay_number] == true) sh.SaveParameter("access_granted_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("access_granted_" + Convert.ToString(relay_number), "0");
                        StorageHandler sh = new StorageHandler();
                        if (App.passage[relay_number] == true) sh.SaveParameter("passage_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("passage_" + Convert.ToString(relay_number), "0");
                        if (unlock_schedule[relay_number] == true) sh.SaveParameter("unlock_schedule_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("unlock_schedule_" + Convert.ToString(relay_number), "0");
                        if (unlock_scheduleTouchScreen[relay_number] == true) sh.SaveParameter("unlock_scheduleTS_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("unlock_scheduleTS_" + Convert.ToString(relay_number), "0");
                        if (App.lockdown[relay_number] == true) sh.SaveParameter("lockdown_" + Convert.ToString(relay_number), "1"); else sh.SaveParameter("lockdown_" + Convert.ToString(relay_number), "0");
                    }
                }
    
            }





    Dan DeMerchant

    Wednesday, December 5, 2018 12:56 AM
  • I think I found one problem...leftover piece of code from an old revision...

    public bool NonRecurringHolidayCheck() { try { StorageFolder folder = ActiveDataFolder(); string[] record; string bank = ReturnActiveBank(); string filename = "nonRecurringHoliday" + "_" + bank + ".dat"; if (File.Exists(Path.Combine(folder.Path, filename)) == false) return false;

    var file = folder.OpenStreamForReadAsync(filename);

    int startYear, startMonth, startDate, startHour, startMinute; int endYear, endMonth, endDate, endHour, endMinute; DateTime startDateTime, endDateTime; using (StreamReader reader = File.OpenText(Path.Combine(folder.Path, filename)))//new StreamReader(file)) { while (reader.Peek() >= 0) { //look through the recurring holiday file and see if we are in a recurring holiday this year string line = reader.ReadLine(); record = line.Split('|'); startYear = Convert.ToInt16(record[1].Substring(4, 4)); startMonth = Convert.ToInt16(record[1].Substring(0, 2)); startDate = Convert.ToInt16(record[1].Substring(2, 2)); startHour = Convert.ToInt16(record[1].Substring(8, 2)); startMinute = Convert.ToInt16(record[1].Substring(10, 2)); endYear = Convert.ToInt16(record[1].Substring(16, 4)); endMonth = Convert.ToInt16(record[1].Substring(12, 2)); endDate = Convert.ToInt16(record[1].Substring(14, 2)); endHour = Convert.ToInt16(record[1].Substring(20, 2)); endMinute = Convert.ToInt16(record[1].Substring(22, 2)); startDateTime = new DateTime(startYear, startMonth, startDate, startHour, startMinute, 0); endDateTime = new DateTime(endYear, endMonth, endDate, endHour, endMinute, 0); if ((App.deviceDateTime/*DateTime.Now2*/ >= startDateTime) && (App.deviceDateTime/*DateTime.Now2*/ < endDateTime)) { return true; } } } return false; } catch (Exception) { return false; } finally { } }



    Dan DeMerchant

    Wednesday, December 5, 2018 7:03 AM
  • Is it weird that Visual Studio did not complain about having a random Async line of code in a function that is not marked as Async?  var file = folder.OpenStreamForReadAsync(filename);



    Dan DeMerchant

    Wednesday, December 5, 2018 1:53 PM
  • Hello danoplus,

    Has the memory leak issue solved? If not you can use Profile memory usage in Visual Studio to check objects of Managed and Native to see which cause the issue.

    Ref: "Analyze memory usage data"

    And about Visual Studio issue you can ask at this forum.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, December 7, 2018 2:46 AM
    Moderator
  • Rita,

    It seems to be solved.  What is strange is that the declaration for that extra line of code should never execute because of a file check before it.  In my case the file was absent but that line of code seems to have caused the memory leak.  What is also strange is that that line of code is Async but the block was not marked as Async and Visual Studio didn't care at all...I am still investigating...running the code less often makes the potential leak less evident.


    Dan DeMerchant


    • Edited by danoplus Friday, December 7, 2018 5:02 AM
    Friday, December 7, 2018 5:02 AM