简体   繁体   中英

Non-Static and Static method and class memory allocation

Static question:

In my C# based application I must use some static method from a static class. This is a part of my code:

        //Timer Event (interval: 100ms)
        private void OnTimedEvent2(object source, ElapsedEventArgs e)
        {
            try
            {
                //...

                DataUpdaterClass.Update("SomeString");

                //...
            }

            catch (Exception ex)
            {
                //...
            }

My question is, if I call the Update method in every TimerTick, will it allocate memory in every time or just once?

Non-Static question:

Same Timer but a non-static method.

        static IPEndPoint MyIPEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999);
        static Socket MySocket = null;

        ////Timer Event (interval: 100ms)
        private void OnTimedEvent2(object source, ElapsedEventArgs e)
        {
            try
            {
                if (MySocket == null)
                {
                    MySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    MySocket.Connect(MyIPEndPoint);
                }

                 //...
            }

            catch (Exception ex)
            {
                MySocket.Dispose();
                MySocket = null;
            }
        }

My second question is, if I the program throw an error, then will be my Socket released and will not use any memory in the future?

Lots of Thanks.

EDIT:

Thanks for your answers. I feel I need to add some extra information for you.

My application is a Windows Service which collets data from industrial devices from our factory about the products weight. So it needs to run continuously. Now I'm checking the used memory by my Service and I see that it is always even bigger. It is grows very slowly and I see that the GC makes its job, but the used memory still growing. I post my complete Timer event and the Update method also. I hope you can help me.

The names of the classes, the variables, and the methods are Hungarian, I hope it will not cause problems.

Timer event:

        static string Adat1 =static string IP1 = Convert.ToString(_3DESDekodoloClass.Decrypt(ConfigurationManager.AppSettings["merleg_1_IP"]));
        static int Port1 =Convert.ToInt32(_3DESDekodoloClass.Decrypt(ConfigurationManager.AppSettings["merleg_1_Port"]));
        static int Olvasott1 = 0;
        IPEndPoint Vegpont1 = new IPEndPoint(IPAddress.Parse(IP1), Port1);
        Socket Merleg1 = null;
        static byte[] Buffer1 = new byte[1024];

        //Starts in the OnStart() event.
        private void OnTimedEvent1(object source, ElapsedEventArgs e)
        {
            try
            {
                if (Merleg1 == null)
                {
                    Merleg1 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    Merleg1.Connect(Vegpont1);
                }

                Olvasott1 = Merleg1.Receive(Buffer1);
                Adat1 = Encoding.ASCII.GetString(Buffer1, 0, Olvasott1);
                AdafeltoltoClass.Merleg_1_adatfeltolto(Adat1);
            }

            finally
            {
                if (Merleg1 != null)
                {
                    Merleg1.Dispose();
                }

                Merleg1 = null;
            }
        }

And this is my Update method:

        static AnritsuDataCollector fo_osztaly = new AnritsuDataCollector();

        static SqlDataAdapter sda_1 = new SqlDataAdapter();
        static SqlDataAdapter sda_2 = new SqlDataAdapter();

        static SqlDataAdapter sda_gauss_1 = new SqlDataAdapter();
        static SqlDataAdapter sda_gauss_2 = new SqlDataAdapter();

        //Adatok kinyerése a config fájlból dekódolás után.
        static string data_source = _3DESDekodoloClass.Decrypt(ConfigurationManager.AppSettings["data_source"]);
        static string initial_catalog = _3DESDekodoloClass.Decrypt(ConfigurationManager.AppSettings["initial_catalog"]);
        static string user_id = _3DESDekodoloClass.Decrypt(ConfigurationManager.AppSettings["user_id"]);
        static string password = _3DESDekodoloClass.Decrypt(ConfigurationManager.AppSettings["password"]);

        static string ProductId1 = "";
        static string RankCode1 = "";
        static string Suly1 = "";

        static string ProductId2 = "";
        static string RankCode2 = "";
        static string Suly2 = "";

        internal static void Merleg_1_adatfeltolto(string beerkezo)
        {
            try
            {
                //Az "con" SQL kapcsolat Pool-ba tétele.
                using (SqlConnection con = new SqlConnection(@"Data Source=" + data_source + ";Initial Catalog=" + initial_catalog + ";User ID=" + user_id + ";Password=" + password + ";"))
                {
                    //A kapcsolat megnyitása.
                    con.Open();

                    ProductId1 = beerkezo.Substring(4, 2);
                    RankCode1 = beerkezo.Substring(6, 1);
                    Suly1 = beerkezo.Substring(7, 5);

                    //Ha a suly tartalmaz szóközt.
                    if (Suly1.Contains(' '))
                    {
                        Suly1 = "00.00";
                    }

                    //SQL parancs az adatok feltöltéséhez.
                    using (sda_1.InsertCommand = new SqlCommand("INSERT INTO meresek (product_id, rank_code, merleg, suly, ido) VALUES (@product_id, @rank_code, @merleg, @suly, @ido)", con))
                    {

                        sda_1.InsertCommand.Parameters.Add("@product_id", SqlDbType.Int).Value = Convert.ToInt32(ProductId1);
                        sda_1.InsertCommand.Parameters.Add("@rank_code", SqlDbType.VarChar).Value = Convert.ToString(RankCode1);
                        sda_1.InsertCommand.Parameters.Add("@merleg", SqlDbType.Int).Value = 1;
                        sda_1.InsertCommand.Parameters.Add("@suly", SqlDbType.Float).Value = Convert.ToDouble(Suly1.Replace('.', ','));
                        sda_1.InsertCommand.Parameters.Add("@ido", SqlDbType.DateTime).Value = DateTime.Now;

                        //Az SQL utasítás elküldése a szervernek
                        sda_1.InsertCommand.ExecuteNonQuery();
                    }

                    using (sda_gauss_1.UpdateCommand = new SqlCommand("IF EXISTS(SELECT ROUND(suly,0) FROM gauss_statisztika_merleg_1 WHERE ROUND(suly,0) = @suly AND product_id = @product_id) BEGIN UPDATE gauss_statisztika_merleg_1 SET darab = darab + 1, utolso_meres = @utolso_meres WHERE ROUND(suly,0) = @suly AND product_id = @product_id END ELSE BEGIN INSERT INTO gauss_statisztika_merleg_1 VALUES(@product_id, @suly, 1, 1, @utolso_meres) END", con))
                    {
                        sda_gauss_1.UpdateCommand.Parameters.Add("@suly", SqlDbType.Float).Value = Math.Round(Convert.ToDouble(Suly1.Replace('.', ',')));
                        sda_gauss_1.UpdateCommand.Parameters.Add("@product_id", SqlDbType.Int).Value = Convert.ToInt32(ProductId1);
                        sda_gauss_1.UpdateCommand.Parameters.Add("@utolso_meres", SqlDbType.DateTime).Value = DateTime.Now;

                        sda_gauss_1.UpdateCommand.ExecuteNonQuery();
                    }
                }
            }

            catch (Exception ex)
            {
                fo_osztaly.Eventlog.WriteEntry(ex.Message);
            }
        }

Static question: Calling of already subscribed handlers will not trigger memory allocation. Code is already in memory. Code execution may trigger memory allocation.

Non-Static question: You cannot guarantee when object will be removed from memory - so answer is may be. Your sample has an error - you should change "catch" to "finaly" and check that MySocket is not null before dispose.

Other: Based on your questions, I don't thinkg that it makes sense for you to pay much attention to effective usage of memory. It is managed language and most of memory management stuff is done by .NET framework itself

question #1: you your OnTimedEvent2 you call a static method: compiler will not allocate any memory for this, just put the code to call the method. What within the method it's another pair of sleeves: if it allocates memory, it will for every call. But really, it depends on DataUpdaterClass.Update implementation.

question #2: setting MySocket variable to null, and therefore removing all reference to the allocated socket, will allow the Garbage Collector to free the memory. GC will free it according to its own logic. So yes, you can consider that the memory used by the allocated socket will be released.

As a side note: don't focus on memory management so much. .NET implemented Garbage Collection to free the developper from memory management issues. And I never found a case where GC didn't do its job properly.

There are cases where you have to care to how much memory your software is allocating and not releasing, your two cases are not among them

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM