So I have a background service written in C# which connects to a RFID-reader and reads out all the tags he sees. After that the service will place all tags in a database running on the Raspberry Pi as well. The problem is when I start the service that it keeps consuming more and more memory from the Pi. I've already ran it with mono-service --profile=default:alloc but this returns errors. Does anybody see anything in my code which could cause this memory usage?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using Impinj.OctaneSdk;
using MySql.Data.MySqlClient;
using Raspberry.IO.GeneralPurpose;
using System.IO.Ports;
using System.Xml;
using System.Threading;
namespace RFIDdaemon
{
public partial class RFIDdaemon : ServiceBase
{
// Create an instance of the ImpinjReader class.
static ImpinjReader reader = new ImpinjReader();
static int opIdUser, opIdTid;
static MySQL _oMySql = new MySQL(Properties.Resources.DatabaseHostname, Properties.Resources.Database, Properties.Resources.Uid, Properties.Resources.Pwd);
// Create a Dictionary to store the tags we've read.
static OutputPinConfiguration led1 = ConnectorPin.P1Pin18.Output();
static GpioConnection connection = new GpioConnection(led1);
static XmlDocument Power = new XmlDocument();
private Thread _oThread;
private ManualResetEvent _oManualResetEvent = new ManualResetEvent(false);
static string userData, tidData, epcData;
public RFIDdaemon()
{
this.ServiceName = "RFIDdaemon";
this.AutoLog = false;
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (_oThread == null)
{
_oThread = new Thread(Reader);
}
if (!_oThread.IsAlive)
{
_oManualResetEvent.Reset(); //Reset reset event te continue thread
_oThread = new Thread(Reader); //New thread
_oThread.Name = "RFIDreader";
_oThread.IsBackground = true;
_oThread.Start();
}
}
protected override void OnStop()
{
// Stop reading.
reader.Stop();
GC.Collect();
// Disconnect from the reader.
reader.Disconnect();
connection.Close();
}
static void Reader()
{
try
{
// Connect to the reader.
// Change the ReaderHostname constant in SolutionConstants.cs
// to the IP address or hostname of your reader.
reader.Connect(Properties.Resources.ReaderIP);
// Assign the TagOpComplete event handler.
// This specifies which method to call
// when tag operations are complete.
reader.TagOpComplete += OnTagOpComplete;
// Get the default settings
// We'll use these as a starting point
// and then modify the settings we're
// interested in.
Settings settings = reader.QueryDefaultSettings();
double[] Results = ReadXml();
if(Results != null)
{
settings.Antennas.GetAntenna(1).TxPowerInDbm = Results[0];
settings.Antennas.GetAntenna(1).RxSensitivityInDbm = Results[1];
}
// Create a tag read operation for User memory.
TagReadOp readUser = new TagReadOp();
// Read from user memory
readUser.MemoryBank = MemoryBank.User;
// Read two (16-bit) words
readUser.WordCount = 2;
// Starting at word 0
readUser.WordPointer = 0;
// Create a tag read operation for TID memory.
TagReadOp readTid = new TagReadOp();
// Read from TID memory
readTid.MemoryBank = MemoryBank.Tid;
// Read two (16-bit) words
readTid.WordCount = 8;
// Starting at word 0
readTid.WordPointer = 0;
// Add these operations to the reader as Optimized Read ops.
// Optimized Read ops apply to all tags, unlike
// Tag Operation Sequences, which can be applied to specific tags.
// Speedway Revolution supports up to two Optimized Read operations.
settings.Report.OptimizedReadOps.Add(readUser);
settings.Report.OptimizedReadOps.Add(readTid);
// Store the operation IDs for later.
opIdUser = readUser.Id;
opIdTid = readTid.Id;
// Apply the newly modified settings.
reader.ApplySettings(settings);
// Start reading.
reader.Start();
}
catch (OctaneSdkException e)
{
// Handle Octane SDK errors.
Console.WriteLine("Octane SDK exception: {0}", e.Message);
//Console.ReadLine();
}
catch (Exception e)
{
// Handle other .NET errors.
Console.WriteLine("Exception : {0}", e.Message);
}
}
// This event handler will be called when tag
// operations have been executed by the reader.
static void OnTagOpComplete(ImpinjReader reader, TagOpReport report)
{
try
{
userData = tidData = epcData = "";
// Loop through all the completed tag operations
foreach (TagOpResult result in report)
{
// Was this completed operation a tag read operation?
if (result is TagReadOpResult)
{
// Cast it to the correct type.
TagReadOpResult readResult = result as TagReadOpResult;
// Save the EPC
epcData = readResult.Tag.Epc.ToHexString();
// Are these the results for User memory or TID?
if (readResult.OpId == opIdUser)
userData = readResult.Data.ToHexString();
if (readResult.OpId == opIdTid)
tidData = readResult.Data.ToHexString();
if (epcData != "")
{
InsertTag(epcData, tidData, userData, DateTime.Now);
}
readResult = null;
}
}
userData = tidData = epcData = null;
}
catch
{
}
}
static void InsertTag(string EPC, string TID, string User, DateTime TagreadTime)
{
try
{
DataTable Time = _oMySql.Select("SELECT Tijd FROM biketable WHERE EPC = '" + EPC + "';").Tables[0];
DateTime OldTime = Convert.ToDateTime(Time.Rows[0][0]);
TimeSpan diff = TagreadTime.Subtract(OldTime);
string formatForMySql = TagreadTime.ToString("yyyy-MM-dd HH:mm:ss");
if (diff.TotalSeconds > 20)
{
connection.Blink(led1, 100);
if (_oMySql.Select("SELECT Binnen From biketable WHERE EPC = '" + EPC + "';").Tables[0].Rows[0][0].ToString() == "True")
_oMySql.Update("UPDATE biketable SET Tijd = '" + formatForMySql + "', TID = '" + TID + "', UserMem ='" + User + "', Binnen = 'False' WHERE EPC = '" + EPC + "';");
else
_oMySql.Update("UPDATE biketable SET Tijd = '" + formatForMySql + "', TID = '" + TID + "', UserMem ='" + User + "', Binnen = 'True' WHERE EPC = '" + EPC + "';");
}
Time = null;
formatForMySql = null;
}
catch
{
}
}
static double[] ReadXml()
{
double[] Results = new double[2];
try
{
string dir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Power.Load(dir + @"\\Power.XML");
XmlNodeList TXpower = Power.GetElementsByTagName("TXpower");
XmlNodeList RXpower = Power.GetElementsByTagName("RXpower");
Results[0] = System.Convert.ToDouble(TXpower[0].InnerXml);
Results[1] = System.Convert.ToDouble(RXpower[0].InnerXml);
return Results;
}
catch (Exception e)
{
return null;
}
}
}
}
when I run tail -n 1000 /var/log/syslog I get the following messages: note the last messages where it kills the service
http://cl.ly/image/343p2i2y251L
How can I easily detect the memory leak?
Thanks in advance