簡體   English   中英

非靜態和靜態方法和類內存分配

[英]Non-Static and Static method and class memory allocation

靜態問題:

在基於C#的應用程序中,我必須使用靜態類中的某些靜態方法。 這是我的代碼的一部分:

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

                DataUpdaterClass.Update("SomeString");

                //...
            }

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

我的問題是,如果我在每個TimerTick,中都調用Update方法TimerTick,它將是每次分配內存還是一次分配內存?

非靜態問題:

相同的Timer但非靜態方法。

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

我的第二個問題是,如果我的程序拋出錯誤,那么我的Socket將被釋放並且將來不會使用任何內存嗎?

非常感謝。

編輯:

感謝您的回答。 我覺得我需要為您添加一些其他信息。

我的應用程序是Windows服務,它可以收集來自我們工廠的工業設備中有關產品重量的數據。 因此它需要連續運行。 現在,我正在通過服務檢查已使用的內存,並且看到它總是更大。 它的增長非常緩慢,我看到GC可以完成工作,但是使用的內存仍在增長。 我發布了完整的Timer事件和Update方法。 我希望你能幫助我。

類,變量和方法的名稱是匈牙利語,希望不會引起問題。

計時器事件:

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

這是我的Update方法:

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

靜態問題:調用已訂閱的處理程序不會觸發內存分配。 代碼已在內存中。 代碼執行可能會觸發內存分配。

非靜態問題:您不能保證何時將對象從內存中刪除-答案可能是。 您的示例有一個錯誤-您應將“ catch”更改為“ finaly”,並在處置之前檢查MySocket是否為null。

其他:根據您的問題,我認為您不應該特別注意內存的有效使用。 它是托管語言,大多數內存管理工作都是由.NET框架本身完成的

問題#1:您在OnTimedEvent2調用了靜態方法:編譯器不會為此分配任何內存,只需將代碼放入即可調用該方法。 在該方法中,還有另外兩套方法:如果它分配內存,它將用於每次調用。 但實際上,這取決於DataUpdaterClass.Update實現。

問題2:將MySocket變量設置為null,從而刪除對分配的套接字的所有引用,將使垃圾回收器釋放內存。 GC將根據自己的邏輯釋放它。 所以是的,您可以考慮分配的套接字使用的內存將被釋放。

附帶說明:不要過多地關注內存管理。 .NET實現了Garbage Collection,以使開發人員擺脫內存管理問題。 而且我從來沒有發現GC無法正常工作的情況。

在某些情況下,您必須注意軟件分配和不釋放的內存量,這兩種情況不在其中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM