Hi there,
I am building a live data logger (basically a counter) which sends counts (collected by a photo sensor) to a webpage in a querystring so the data can be added to a SQL DB.
To make sure that I have a redundancy, in the event of power failure for example, I have two files on an SD card which the counter writes to on the photo sensor interrupt. Periodically the SD card is read and the data put into an array which is then looped through to send the HTTP requests. This prevents any issues of trying to read from the SD card at the same time as a photo interrupt is trying to write to the card.
I'm using a Netduino Plus 2.
At the moment I am testing a part of the final code and have encountered a "memory leak" issue.
Basically I am simply looping through the "SD Card read" and "array send threads" to test them. the problem I am having is that I eventually run out of memory and I can't understand why.
I would have thought that the only thing taking up memory would be the counter variable (which is the only thing that changes with each request... it's increased by one) but for whatever reason on each loop I lose about 3500 bytes.
I have made sure that I flush/close/dispose both the stream reader and stream writer (used for writing errors to a log file) when I am finished using them. I also clear the array when i am done with it.
Surely increasing the counter variable by an increment of 1 is not 3500 bytes worth of memory?
Do I need to abort/close threads as I leave them? Is it something to do with the "Socket" or "WebSession"... do I need to somehow terminate/clear these before creating new ones?
using System;using System.Collections;using System.IO;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;using Microsoft.SPOT;using Microsoft.SPOT.Hardware;using SecretLabs.NETMF.Hardware;using SecretLabs.NETMF.Hardware.Netduino;using Toolbox.NETMF.Hardware;using Toolbox.NETMF.NET;using VariableLabs.PowerManagment;namespace testToolbox21240{ public class Program { static WiFlyGSX WifiModule; static ArrayList counterDataArray = new ArrayList(); // SD Card file variables static string strWriteFile = "datatwo"; static string strReadFile = "dataone"; // WiFi SSID and password static string strSSID = "mySSID"; static string strPassword = "myPassword"; // Remote host URL static string strRemoteHost = "myUrl.com"; // Counter variables static uint intCounter = 0; static uint intTimeoutCounter = 0; public static void Main() { Debug.Print("Turn off the Ethernet controller"); PowerManagment.SetPeripheralState(Peripheral.Ethernet, false); Debug.EnableGCMessages(true); connectToWifi(); populateArray(); Thread.Sleep(Timeout.Infinite); } public static void populateArray() { Debug.Print("Populate array from: " + strReadFile); using (var filestream = new FileStream(@"SD" + strReadFile + ".txt", FileMode.Open)) { string strSendLine; StreamReader sr = new StreamReader(filestream); while ((strSendLine = sr.ReadLine()) != null) { counterDataArray.Add(strSendLine); } sr.Close(); sr.Dispose(); } Debug.Print("send data from array"); foreach (string value in counterDataArray) { httpSendData(value); } cleanUp(); } public static void httpSendData(string queryStringData) { SimpleSocket Socket = new WiFlySocket(strRemoteHost, 80, WifiModule); HTTP_Client WebSession = new HTTP_Client(Socket); try { HTTP_Client.HTTP_Response Response = WebSession.Get("/default.aspx?" + queryStringData); Debug.Print("value: " + queryStringData); } catch (System.ApplicationException e) { Debug.Print("Error Code: " + e); intTimeoutCounter++; Debug.Print("intTimeoutCounter: " + intTimeoutCounter); using (var filestream = new FileStream(@"SDlog.txt", FileMode.Append)) { StreamWriter sw = new StreamWriter(filestream); sw.WriteLine("DateTime: " + DateTime.Now.AddHours(2) + "rnError Code: " + e + "rnintTimeoutCounter: " + intTimeoutCounter + "rn"); sw.Flush(); sw.Close(); sw.Dispose(); } Thread.Sleep(1500); httpSendData(queryStringData); } catch (System.NullReferenceException f) { Debug.Print("Error Code: " + f); using (var filestream = new FileStream(@"SDlog.txt", FileMode.Append)) { StreamWriter sw = new StreamWriter(filestream); sw.WriteLine("DateTime: " + DateTime.Now.AddHours(2) + "rnError Code: " + f + "rnintTimeoutCounter: " + intTimeoutCounter + "rn"); sw.Flush(); sw.Close(); sw.Dispose(); } } finally { intCounter++; } } public static void cleanUp() { if (strWriteFile == "dataone") { strWriteFile = "datatwo"; strReadFile = "dataone"; } else { strWriteFile = "dataone"; strReadFile = "datatwo"; } counterDataArray.Clear(); Debug.GC(true); Debug.Print("Free Memory: " + Debug.GC(true).ToString()); Debug.Print("Record count: " + intCounter); Debug.Print("running thread count: " + ThreadState.Background.ToString()); populateArray(); } public static void connectToWifi() { Debug.Print("start wifi"); WifiModule = new WiFlyGSX(); WifiModule.EnableDHCP(); WifiModule.JoinNetwork(strSSID, 0, WiFlyGSX.AuthMode.MixedWPA1_WPA2, strPassword); Thread.Sleep(3500); // Showing some interesting output Debug.Print("Local IP: " + WifiModule.LocalIP); Debug.Print("MAC address: " + WifiModule.MacAddress); SNTP_Client TimeClient = new SNTP_Client(new WiFlySocket("ntp2.is.co.za", 123, WifiModule)); Thread.Sleep(500); TimeClient.Synchronize(); Thread.Sleep(500); Debug.Print("DateTime.Now: " + DateTime.Now.AddHours(2)); Thread.Sleep(3500); } }}
A snippet of the debug output:
The thread '<No Name>' (0x2) has exited with code 0 (0x0).Turn off the Ethernet controllerstart wifiLocal IP: 192.168.0.8MAC address: 00:60:06:80:88:55DateTime.Now: 01/10/2013 12:02:16Populate array from: dataonesend data from arrayvalue: deviceID=1&count=0&dateTimeStamp=12/5/2012%2017:8:5value: deviceID=1&count=1&dateTimeStamp=12/5/2012%2017:8:6value: deviceID=1&count=2&dateTimeStamp=12/5/2012%2017:8:7value: deviceID=1&count=3&dateTimeStamp=12/5/2012%2017:8:7value: deviceID=1&count=4&dateTimeStamp=12/5/2012%2017:8:8[color=#ff0000;]Free Memory: 99072[/color]Record count: 5running thread count: 4Populate array from: datatwosend data from arrayvalue: deviceID=1&count=5&dateTimeStamp=12/7/2012%2013:31:33value: deviceID=1&count=6&dateTimeStamp=12/7/2012%2013:31:34value: deviceID=1&count=7&dateTimeStamp=12/7/2012%2013:32:24value: deviceID=1&count=8&dateTimeStamp=12/7/2012%2013:32:24value: deviceID=1&count=9&dateTimeStamp=12/7/2012%2013:32:24value: deviceID=1&count=10&dateTimeStamp=12/7/2012%2013:32:24value: deviceID=1&count=11&dateTimeStamp=12/7/2012%2013:32:24value: deviceID=1&count=12&dateTimeStamp=12/7/2012%2013:32:25value: deviceID=1&count=13&dateTimeStamp=12/7/2012%2013:32:25value: deviceID=1&count=14&dateTimeStamp=12/7/2012%2013:32:25value: deviceID=1&count=15&dateTimeStamp=12/7/2012%2013:32:25value: deviceID=1&count=16&dateTimeStamp=12/7/2012%2013:32:25[color=#ff0000;]Free Memory: 95544[/color]Record count: 17running thread count: 4
Thanks for any advice!
Donovan