mono-service продолжает резервировать память до тех пор, пока в Raspberry Pi не закончится память

Итак, у меня есть фоновый сервис, написанный на C#, который подключается к RFID-считывателю и считывает все теги, которые он видит. После этого сервис поместит все теги в базу данных, также работающую на Raspberry Pi. Проблема в том, что когда я запускаю службу, она потребляет все больше и больше памяти от Pi. Я уже запускал его с моносервисом --profile=default:alloc, но это возвращает ошибки. Кто-нибудь видит что-нибудь в моем коде, что может привести к такому использованию памяти?

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;
            }
        }
    }
}

когда я запускаю tail -n 1000 /var/log/syslog, я получаю следующие сообщения: обратите внимание на последние сообщения, где он убивает службу

http://cl.ly/image/343p2i2y251L

Как я могу легко обнаружить утечку памяти?

заранее спасибо


person BertVano    schedule 11.09.2014    source источник
comment
Вы создаете две темы в OnStart()? - Возможно, взгляните на stackoverflow.com/questions/15860481/ и пытаюсь возиться с MONO_GC_PARAMS.   -  person JimmyB    schedule 11.09.2014