PDA

View Full Version : حرفه ای: اشکال در آزاد نکردن منابع در استفاده از openfiledialoge()



parham2501
چهارشنبه 29 خرداد 1392, 00:05 صبح
باسلام خدمت دوستان عزیز
من هنگام استفاده از کلاس openfiledialoge() با یه مشکل مواجه شدم و اون این هست که من یک شی از این کلاس ایجاد کردم و توسط تابع showdialoge() اونو نمایش میدم و فایل عکس مورد نظرم رو انتخاب میکنم. حالا بعد از اینکه ok میکنم این کلاس به صورت کامل از حافظه خارج نمیشه و انگار یه سری stream و dll رو به سیستم عامل پس نمیده. از متد Dispose و GC هم استفاده کردم ولی بازهمین مشکل وجود داره. من از .net framwork 2 استفاده میکنم. چرا این مشکل وجود داره و dispose نمیتونه کل منابع دریافتی رو به سیستم برگردونه؟
برای تست کافیه یه فرم ایجاد کنید یه openfiledialoge بزارید رو فرم و یه button برای نمایشش. حالا یه فلش مموری به سیستم وصل کنید و یه فایل رو ازش انتخاب کنید و مثلا توی یه picturebox نمایشش بدید. حالا فرمی رو که با متد showdialoge فراخونی کردید dispose کنید یا هربلایی میخواید سرش بیارید تا منابع رو به سیستم برگردونه. حالا برید سراغ فلش و اونو به صورت safely remove از سیستم جداش کنید. میبینید که هنوز داره ازش استفاده میشه و اجازه ی اینکارو بهتون نمیده. اگرم همینطوری جداش کنید از سیستم و بعدا بخواید دوباره از فرمتون یه عکس دیگه لود کنید میبینید که با ارور مواجه میشید.
حالا سوال من اینه که چطوری میتونیم کل منابعی که ای فرم دریافت کرده رو به سیستم عامل پس داد و رم رو خالی کرد از dllهایی که لود شدن.
در ضمن در دفعه ی اول اگه تو دیباگ نگاه کنید میبینید کلی Dll لود میکنه ولی دفعه های بعد فقط چندتا dll لود میکنه این نشون میده که اونا هنوز در حال استفاده هستن. چطوری میشه آخه اینکارو کرد. باید به زمان داس برگردیم دوباره با رم و حافظه این چیزاهم سر و کله بزنیم دوباره واسه پس دادن منابع. خوبه حالا اینقد پیشرفت کرده برنامه نویسی ولی واسه یه dispose ساده با همچین مشکلی مواجه هستیم.:عصبانی++:

از دوستان برنامه نویس که تجربه در این زمینه دارند و میدونن چطوری میشه memory leak رو از بین برد خواهش میکنم به این سوال جواب بدید.
حتی از SciTech.NetMemProfiler که کلی متدوکلاس برای مدیریت حافظه داره استفاده کردم ولی بازم پس نمیده منابع رو. عجیبه واقعا!!!!!حسابی گذاشته مارو سرکار.:عصبانی:

Mahmoud.Afrad
چهارشنبه 29 خرداد 1392, 01:39 صبح
دو تا راه داری.
یکی اینکه اگر از خصوصیت Image پیکچرباکس استفاده کردی ، موقع بستن فرم باید متغیر Image را Dispose کنی:

private void button1_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
pictureBox1.Image = Image.FromFile(ofd.FileName);
}
}
}

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.pictureBox1.Image != null)
{
this.pictureBox1.Image.Dispose();
}
}

راه دیگه هم اینه که از خصوصیت ImageLocation به جای Image استفاده کنی:

private void button1_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
pictureBox1.ImageLocation = ofd.FileName;
}
}
}

esafb52
چهارشنبه 29 خرداد 1392, 01:45 صبح
دو تا راه داری.
یکی اینکه اگر از خصوصیت Image پیکچرباکس استفاده کردی ، موقع بستن فرم باید متغیر Image را Dispose کنی:

private void button1_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
pictureBox1.Image = Image.FromFile(ofd.FileName);
}
}
}

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.pictureBox1.Image != null)
{
this.pictureBox1.Image.Dispose();
}
}

راه دیگه هم اینه که از خصوصیت ImageLocation به جای Image استفاده کنی:

private void button1_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
pictureBox1.ImageLocation = ofd.FileName;
}
}
}

با سلام به شما استاد گرامی هدف از استفاده از این using ها در بین کد چیست؟؟

ashkan1234
چهارشنبه 29 خرداد 1392, 09:42 صبح
با سلام!
Using به محض اینکه فرمانهای داخل بلاکهاش رو انجام داد و تموم شد،حافظه اشغال شده رو آزاد میکنه!
موفق باشید!

hamid_hr
چهارشنبه 29 خرداد 1392, 10:11 صبح
بايد مسير جاري رو عوض كني
System.IO.Directory.SetCurrentDirectory("c:\\");
من تست كردم درست شد

parham2501
دوشنبه 17 تیر 1392, 22:04 عصر
بايد مسير جاري رو عوض كني
System.IO.Directory.SetCurrentDirectory("c:\\");
من تست كردم درست شد

باتشکر از پاسخ شما، بله با این trick این مشکل حل میشه. خیلی ممنون بابت راهنمایی خوب شما.

وبهتره به علت اضافه نشدن به حجم حافظه در هربار اجرا شدن از دستور
GC.Collect();
بعد از کد فوق استفاده کنیم

موفق باشی دوست عزیز