لماذا هذا يسبب تسرب الذاكرة؟
-
23-08-2019 - |
سؤال
هذا مثير للاهتمام. لقد أمضينا اليوم الأخير في محاولة تصحيح مشكلة مع الرمز (الإرث) التالي الذي يستمر في تنمو حجم العملية. يتم ذلك في Visual Studio 2003.
لدينا نموذج الذي نعرضه صورة (من موعد المناصب) وبعض النص والزر. لا شيء يتوهم. يبدو شيئا مثل هذا:
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
Try
m_lblWarning.Visible = False
m_grpTitle.Text = m_StationInterface.ProcessToolTitle
m_lblMessage.Text = m_StationInterface.ProcessToolMessage
Dim objImage As MemoryStream
Dim objwebClient As WebClient
Dim sURL As String = Trim(m_StationInterface.ProcessToolPicLocation)
objwebClient = New WebClient
objImage = New MemoryStream(objwebClient.DownloadData(sURL))
m_imgLiftingEye.Image = Image.FromStream(objImage)
m_txtAcknowledge.Focus()
Catch ex As Exception
'*** This handles a picture that cannot be found without erroring'
m_lblWarning.Visible = True
End Try
End Sub
كثيرا ما يتم إغلاق هذا النموذج وفتحه. في كل مرة يتم فيها إعادة فتحها، ينمو استخدام ذاكرة العملية بنسبة 5 ميغابايت تقريبا. عندما يتم إغلاق النموذج، فإنه لا يتراجع إلى استخدامه السابق. تظل الموارد مخصصة للنموذج غير المعهد. يتم تقديم النموذج مثل هذا:
m_CJ5Form_PTOperatorAcknowlegement = New CJ5Form_PTOperatorAcknowlegement
m_CJ5Form_PTOperatorAcknowlegement.stationInterface = m_StationInterface
m_CJ5Form_PTOperatorAcknowlegement.Dock = DockStyle.Fill
Me.Text = " Acknowledge Quality Alert"
'*** Set the size of the form'
Me.Location = New Point(30, 30)
Me.Size = New Size(800, 700)
Me.Controls.Add(m_CJ5Form_PTOperatorAcknowlegement)
تتم إزالة عنصر التحكم في وقت لاحق من النموذج بعد إغلاق:
Me.Controls.Clear()
حاليا. لقد حاولنا العديد من الأشياء. لقد اكتشفنا أن التخلص لا يفعل شيئا، وبالفعل، انهيار الواجهة لا تلمس الذاكرة في الواقع. إذا لم ننشئ نموذج CJ5Form_ptoperatorackLEDGement جديد في كل مرة، فإن حجم العملية لا ينمو. ولكن تحميل صورة جديدة في هذا النموذج لا يزال يؤدي حجم العملية إلى النمو باستمرار.
سيكون موضع تقدير أي اقتراحات.
المحلول
عليك أن تتخلص من كائن WebClient الخاص بك وأي موارد أخرى غير مدارية مدارة قد تكون هناك حاجة إليها.
objImage = New MemoryStream(objwebClient.DownloadData(sURL))
objwebClient.Dispose() ' add call to dispose
طريقة أفضل لرمز هي التي ستكون استخدام عبارة "باستخدام":
using objwebClient as WebClient = New WebClient
objImage = New MemoryStream(objwebClient.DownloadData(sURL))
end using
لمزيد من المعلومات، يرجى البحث عن "التخلص من" وتنفيذ النمط "غير قابل للانتعراض" على Google و Stackoverflow.
آخر تلميح آخر: لا تستخدم دفق الذاكرة إذا كان ذلك ممكنا. قم بتحميل الصورة مباشرة من الملف إلا إذا كنت بحاجة إلى الاحتفاظ بها في ذاكرة الوصول العشوائي.
يحرر
إذا فهمت شفرةك بشكل صحيح ربما شيء من هذا القبيل من شأنه أن يعمل:
Dim objImage As MemoryStream
Dim objwebClient As WebClient
Dim sURL As String = Trim(m_StationInterface.ProcessToolPicLocation)
using objwebClient as WebClient = New WebClient
using objImage as MemoryStream = New MemoryStream(objwebClient.DownloadData(sURL))
m_imgLiftingEye.Image = Image.FromStream(objImage)
end using
end using
نصائح أخرى
لا أعرف السبب في الأمر على وجه التحديد تسرب، ولكن يمكنني أن أوصي بأن تنظر إلى استخدام .NET الذاكرة profiler.. وبعد إذا قمت بتشغيل التطبيق الخاص بك باستخدام ذلك، فسوف يعطيك فكرة جيدة جدا عن الأشياء التي لا يتم التخلص منها وتساعدك على استكشاف الأخطاء وإصلاحها. لقد حصلت على نسخة تجريبية مجانية، لكنها تستحق الشراء.