نمایش نتایج 1 تا 9 از 9

نام تاپیک: جلوگیری از افزایش مقدار حافظه در سی شارپ

  1. #1

    Question جلوگیری از افزایش مقدار حافظه در سی شارپ

    سلام وقت همگی بخیر.
    من تو پروژم 5 تا فرم دارم.
    فرم اول وقتی که کاربر لاگین میکنه.
    فرم دوم وقتی که لاگین اوکی بود فرم اصلی رو نشون میده و فرم اول رو که لاگین بود هاید میکنه.
    توی فرم دوم یک دکمه هست که فرم سوم رو بصورت ShowDialog() فراخوانی میکنه. فرم سوم شامل دیتاگریدویو ، چندتا تکست باکس و دکمه هست. تو رویداد form_load در فرم سوم اطلاعاتی رو از دیتابیس میخونه و تو دیتا گریدویو نمایش میده. وقتی کار تموم شد کاربر فرم سوم رو میبنده و کار تمام میشه.

    مشکل اصلی اینجاست که وقت کاربر فرم سوم رو هر بار فراخوانی کنه، یه مقداری رو از حافظه دریافت میکنه و وقتی کاربر فرم رو میبنده دیگه اون فضا رو آزاد نمیکنه. مثلا توی فرم لاگین (فرم اول)حجم برنامه 6 مگابایت هست.
    بعد از نمایش فرم اصلی (فرم دوم) برنامه میشه 9 مگابایت. مشکل اصلی از اینجا شروع میشه که فرم سوم رو میخوام نمایش بدم 3 مگابایت اضافه میشه و حجم برنامه میشه 12 مگابایت. حالا که فرم رو میبندم همون 12 مگابایت باقی میمونه و دفعات بعدی هر بار که فرم سوم رو فراخوانی کنم به حجمش اضافه میشه تا 30 مگابایت هم میرسه. مشکل کار کجاست؟ چجوری میشه همون فضای اشغال شده رو رو آزاد کرد؟

    نکته : من کل گوگل رو زیرورو کردم، یکی نوشته بود باید از using واسه فراخوانی استفاده کنی، یکی گفته بود باید event handler ها رو unregister کنی و یکی هم میگفت GC رو فراخوانی کن.
    (اینجارو نفهمیدم که چجوری باید event handler ها رو unregister کرد.)

    فراخوانی GC کمی مشکل رو برطرف کرد اما کل فضا رو آزاد نمیکه. و الان 1 هفتست که درگیر این مشکلم نمیدونم باید چجوری حلش کرد. ممنون میشم راهنماییم کنید.

  2. #2
    کاربر دائمی آواتار ROSTAM2
    تاریخ عضویت
    اسفند 1390
    محل زندگی
    فارس
    پست
    1,641

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    سلام.
    ما که نمی دونیم از چ متغیرهایی توی کدنویسیت استفاده کردی هر کدوم رو به ی نحوی می تونی برابر با NULL یا Dispose کنی بطوری که مقادیری که به متغیرات دادی حذف بشه ( برای stream هم close می شه استفاده کرد)
    در مورد event handler ها هم از =- تو C#‎‎‎ استفاده می شه.

  3. #3

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    ممنون از راهنماییت.
    ادیت.

  4. #4

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    نقل قول نوشته شده توسط ROSTAM2 مشاهده تاپیک
    سلام.
    ما که نمی دونیم از چ متغیرهایی توی کدنویسیت استفاده کردی هر کدوم رو به ی نحوی می تونی برابر با NULL یا Dispose کنی بطوری که مقادیری که به متغیرات دادی حذف بشه ( برای stream هم close می شه استفاده کرد)
    در مورد event handler ها هم از =- تو C#‎‎‎‎‎‎‎ استفاده می شه.
    ممنون از راهنماییت.
    در واقع کار اصلی فقط با ADO.NET و دیتابیس هست. توی فرم 3 یه دیتاگریدویو هست که دیتا ها رو میریزه تو DataTable و توی دیتاگریدویو نمایش میده. همین.
    این بخش event handler رو نفهمیدم من. یعنی Button_OnClick رو موقع بستن نرم افزار اینجوری بنویسم؟ ممنوم میشم بیشتر راهنمایی کنی :

    this.Button1.Click -= new System.EventHandler(this.Button1_Click);

  5. #5

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    سلام
    دوستمون توضیح دادن اما در تکمیل صحبت شون اینکه منابع در برنامه تون یا از سی شارپ (که managed هست) ، هست یا از کدهای Unmanaged (مثل ++C و ...) یا از هر دو .
    ممکنه در برنامه تون فقط از کد سی شارپ استفاده کنید اما در لایه های پایین تر اش از کدهای Unmanaged استفاده شده باشه (و صرفا شما خبر نداشته باشین . مثل اغلب کنترل ها) .


    - آزادسازی منابع Managed ای که هیچ اشاره گری بهشون وجود نداره ، بصورت خودکار توسط GC انجام میشه . هر چند ، توصیه میشه که شما بصورت دستی این آزادسازی را انجام ندین ، اما با متد GC.Collect هم میتونین بصورت دستی ، درخواست این کار (درخواست آزادسازی منابع Unmanaged ای که هیچ اشاره گری بهشون وجود نداره) را انجام بدین .
    درخواست ، به معنای این نیست که با اجرای اون متد ، همون لحظه حافظه های بدون اشاره گرش پاک میشن . بلکه معمولا در اسرع وقت پاک میشن .

    این کار ، حداقل زمانی که حجم قابل توجهی از حافظه پر نشده ، چندان توصیه نمیشه چون هم در اون لحظه ی اجرای این متد (ولو بسیار بسیار اندک) ، سربار روی پردازنده ایجاد میشه (و کار اضافی میکنه) و مخصوصا اینکه GC که قبل از اون ، منابع را به 3 نسل مختلف (بر اساس قدمت و پیریِ اطلاعات) تقسیم بندی کرد را اطلاعات هر 3 نسل را مسدود میکنه . نسل ها از 0 تا 2 هستند .
    البته میتونین در اورلودهای دیگه ی همون متد ، شماره ی نسل مورد نظرتون را بگید تا فقط در اون نسل عملیات را انجام بده .


    - آزادسازی منابع Unmanaged بدون استفاده .
    اگه کدهای سی شارپی را استفاده میکنین که متد Dispose دارن و شما خودتون کدهاش را بصورت دستی نوشتید (یا خودتون در کدنویسی ، شی جدید برای اون شی ای که اینترفیس IDisposable را پیاده سازی کرد ، نوشتید . یعنی فرضا مثل زمانی که کنترل را با درگ و دراپ در ui میسازید ، نساختید) ، منابع Unmanaged ای که اشاره گری بهش وجود نداره را در این صورت میتونید با استفاده از دستور using یا نهایتا با فراخونی متد Dispose اش ، درخواست آزادسازی را اعلام کنید .

    =====================

    هندلرهای رویدادها هم بعیده که حافظه ی خاصی نیاز داشته باشن که به چشم بیاد.

    طبق چیزی که میگید با دیتابیس کار میکنید ، هر دوی اون نکات را اجرا کنید . چون معمولا دیتابیس های حجیم یا کنترل هایی که باهاش سر کار دارن و اطلاعات فی مابین شون ، این حالت را دارن که سنگین باشن .

    اگه باز هم مشکل دارید ، به اون کار دقت کنید . یعنی فرضا دقت کنید که اول ، متد Dispose را اجرا کرده باشید و بعد ، همه ی اشاره گرهای به اون شی را null کرده باشید و بعدش دستور GC.Collect را اجرا کرده باشید . چون ترتیب ، خیلی مهم هست .

    اگه هنوز مشکل دارید ، از مدیریت حافظه در ویژال استودیو کمک بگیرید که چه شی با چه نوعی داره بیشترین استفاده را میکنه .

  6. #6

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    نقل قول نوشته شده توسط SajjadKhati مشاهده تاپیک
    سلام
    دوستمون توضیح دادن اما در تکمیل صحبت شون اینکه منابع در برنامه تون یا از سی شارپ (که managed هست) ، هست یا از کدهای Unmanaged (مثل ++C و ...) یا از هر دو .
    ممکنه در برنامه تون فقط از کد سی شارپ استفاده کنید اما در لایه های پایین تر اش از کدهای Unmanaged استفاده شده باشه (و صرفا شما خبر نداشته باشین . مثل اغلب کنترل ها) .


    - آزادسازی منابع Managed ای که هیچ اشاره گری بهشون وجود نداره ، بصورت خودکار توسط GC انجام میشه . هر چند ، توصیه میشه که شما بصورت دستی این آزادسازی را انجام ندین ، اما با متد GC.Collect هم میتونین بصورت دستی ، درخواست این کار (درخواست آزادسازی منابع Unmanaged ای که هیچ اشاره گری بهشون وجود نداره) را انجام بدین .
    درخواست ، به معنای این نیست که با اجرای اون متد ، همون لحظه حافظه های بدون اشاره گرش پاک میشن . بلکه معمولا در اسرع وقت پاک میشن .

    این کار ، حداقل زمانی که حجم قابل توجهی از حافظه پر نشده ، چندان توصیه نمیشه چون هم در اون لحظه ی اجرای این متد (ولو بسیار بسیار اندک) ، سربار روی پردازنده ایجاد میشه (و کار اضافی میکنه) و مخصوصا اینکه GC که قبل از اون ، منابع را به 3 نسل مختلف (بر اساس قدمت و پیریِ اطلاعات) تقسیم بندی کرد را اطلاعات هر 3 نسل را مسدود میکنه . نسل ها از 0 تا 2 هستند .
    البته میتونین در اورلودهای دیگه ی همون متد ، شماره ی نسل مورد نظرتون را بگید تا فقط در اون نسل عملیات را انجام بده .


    - آزادسازی منابع Unmanaged بدون استفاده .
    اگه کدهای سی شارپی را استفاده میکنین که متد Dispose دارن و شما خودتون کدهاش را بصورت دستی نوشتید (یا خودتون در کدنویسی ، شی جدید برای اون شی ای که اینترفیس IDisposable را پیاده سازی کرد ، نوشتید . یعنی فرضا مثل زمانی که کنترل را با درگ و دراپ در ui میسازید ، نساختید) ، منابع Unmanaged ای که اشاره گری بهش وجود نداره را در این صورت میتونید با استفاده از دستور using یا نهایتا با فراخونی متد Dispose اش ، درخواست آزادسازی را اعلام کنید .

    =====================

    هندلرهای رویدادها هم بعیده که حافظه ی خاصی نیاز داشته باشن که به چشم بیاد.

    طبق چیزی که میگید با دیتابیس کار میکنید ، هر دوی اون نکات را اجرا کنید . چون معمولا دیتابیس های حجیم یا کنترل هایی که باهاش سر کار دارن و اطلاعات فی مابین شون ، این حالت را دارن که سنگین باشن .

    اگه باز هم مشکل دارید ، به اون کار دقت کنید . یعنی فرضا دقت کنید که اول ، متد Dispose را اجرا کرده باشید و بعد ، همه ی اشاره گرهای به اون شی را null کرده باشید و بعدش دستور GC.Collect را اجرا کرده باشید . چون ترتیب ، خیلی مهم هست .

    اگه هنوز مشکل دارید ، از مدیریت حافظه در ویژال استودیو کمک بگیرید که چه شی با چه نوعی داره بیشترین استفاده را میکنه .
    ممنونم از توضیحات کاملت آقا سعید.
    من توی فرم 3 که از دیتابیس استفاده کردم توی form load ، این کار رو انجام دادم -> توی رویداد form close این 2 تا رو فراخوانی کردم:

    this.Dispose()
    GC.Collect();

    مرحله اول مشکل حل شد = این کار باعث شد فقط یک بار فضای رم اشغال بشه ، یعنی 20 بار هم فرم 3 رو که فراخوانی کردم مقدارش همون بود،(وقتی یکم با کنترل ها مثل دیتاگریدویو و باتن ها کار کردم فضاش خیلی کم رفت بالا)

    مرحله دوم :
    نکته بعدیش اینه وقتی که فرم رو میبندم از اون فضایی که اشغال میکنه 20 کیوبایت رو کم میکنه. یعنی همرو آزاد نمیکنه.
    همونجور که توضیح دادم وقتی هنوز فرم 3 رو فراخوانی نکرده باشم ، حجم اشغال شده 9 مگابایت هست، وقتی فرم 3 رو فراخوانی کردم حجم اشغال شده میشه 12 مگابایت و موقع خروج 3 مگابایت رو آزاد نمیکنه. برای این نشکل چه راه حلی پیشنهاد میکنین؟

    و یک سوال دیگه این که :

    نقل قول نوشته شده توسط SajjadKhati مشاهده تاپیک
    یعنی فرضا دقت کنید که اول ، متد Dispose را اجرا کرده باشید و بعد ، همه ی اشاره گرهای به اون شی را null کرده باشید و بعدش دستور GC.Collect را اجرا کرده باشید . چون ترتیب ، خیلی مهم هست .

    اگه هنوز مشکل دارید ، از مدیریت حافظه در ویژال استودیو کمک بگیرید که چه شی با چه نوعی داره بیشترین استفاده را میکنه .اگه هنوز مشکل دارید ، از مدیریت حافظه در ویژال استودیو کمک بگیرید که چه شی با چه نوعی داره بیشترین استفاده را میکنه .
    چجوری میتونم اشاره گر ها رو null کنم؟ منظورتون همون SqlDataAdapter ، Data Table و SqlConnection هست ؟ ممنون میشم توضیح بدین. مرسی که وقت گذاشتین.
    آخرین ویرایش به وسیله meysamabdolahi : چهارشنبه 22 تیر 1401 در 21:54 عصر

  7. #7

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    نقل قول نوشته شده توسط meysamabdolahi مشاهده تاپیک
    ممنونم از توضیحات کاملت آقا سعید.
    من توی فرم 3 که از دیتابیس استفاده کردم توی form load ، این کار رو انجام دادم -> توی رویداد form close این 2 تا رو فراخوانی کردم:

    this.Dispose()
    GC.Collect();
    سلامی مجدد

    this ، اشاره گر به شی Form_3 تون هست دیگه . درسته؟
    طبعا شیِ Form_3 تون را هم در رویداد دکمه ای که در پست 1 گفته بودید ، خودتون شیِ جدید بهش دادین (new Form_3() کردین) دیگه . درسته؟
    اگه درسته ، در این حالت ، اینکه متد Dispose اش را فراخونی کردین ، درسته .
    اما اگه این ، شی ای بود که توسط کدهای ویژال استودیو نوشته میشد (یعنی خودتون مستقیما شی ایجاد نمیکردید و new نمیکردید) ، لازم نبود متد Dispose را فراخونی کنید .هر چند ، در این حالت هم اشکال چندانی هم نداشت .


    - دوما ، جای مناسب فراخونیِ متد Dispose ، توی رویدادِ خود اون شی یا کنترل زیر مجموعه های اون شی نیست . یعنی رویداد Form Close ئه Form_3 ، جای خوبی برای فراخونی متد Dispose نیست .
    جای مناسب اش ، بعد از اتمام کارش هست . یعنی بعد از اینکه متد Form_3_ShowDialog را فراخونی کردین ، بعد از این متد ، فراخونی متد Dispose ئه Form_3 ، بهترین جاش هست .
    راحت تر هست براتون که Form_3 را توی دستور using بذارید تا مجبور نباشید متد Dispose را فراخونی کنید .


    - سوما ، GC.Collect ، ای که در رویداد form close ئه Form_3 نوشتید ، هیچ تاثیری در پاک کردن داده های Managed ئه Form_3 در اینجا نداره :
    چون اولا شما در رویداد form close ئه Form_3 هستید و هنوز دارید از شیِ Form_3 استفاده میکنید .
    دوما و مهمتر اینکه شما تا اون موقع ، قطعا اشاره گر به شیِ Form_3 را null نکردین و از بین نبردین و قطعا تا اون موقع ، حداقل یک اشاره گر ، به شیِ Form_3 تون داره اشاره میکنه چون رویداد form close ئه Form_3 در حال اجرا شدن هست .

    باید همه ی متغییرهایی که به اون شی اشاره میکنن را اول ، null کنید تا هیچ اشاره گری به اون شی اشاره نکنه و بعدش متد GC.Collect را اجرا کنید .
    جای فراخونی این متدِ GC.Collect هم بعد از فراخونی متد Dispose (یا بعد از دستور using) ، اول ، همه ی متغییرهایی که به اون شی از Form_3 اشاره دارن را null میکنید و بعد از null کردنِ همه شون ، حالا متد GC.Collect را فراخونی میکنید (که در همون رویداد دکمه ای که در پست 1 گفتین ، میشه) .
    ضمنا ، با فراخونی این متد ، شما صرفا درخواست پاک سازی دادید . نه اینکه در همون لحظه پاکسازی انجام میشه .


    - چهارما ، دقت کنید که همه ی کنترل ها و کلا همه ی اشیاهایی که خودتون در کدنویسی ، مقدار جدید بهشون دادین را هم این کار را انجام بدین براشون .
    فرضا ممکنه در یک رویدادی در Form_3 ، یک Button ای را شی جدید داده باشید که در این صورت وظیفه ی شماست که بعد از استفاده ، متد Dispose اش را فراخونی کنید . همچنین حتی برای اینکه حافظه ی Managed اش را آزاد کنید ، بعد از اون ، فرضا اگه در متغییر سراسری تعریف کردید ، وظیفه ی شماست که اول ، null اش کنید و بعد متد GC.Collect را فراخونی کنید .
    همچنین هر شی دیگه ای (نه فقط کنترل ها) .

    نقل قول نوشته شده توسط meysamabdolahi مشاهده تاپیک
    مرحله اول مشکل حل شد = این کار باعث شد فقط یک بار فضای رم اشغال بشه ، یعنی 20 بار هم فرم 3 رو که فراخوانی کردم مقدارش همون بود،(وقتی یکم با کنترل ها مثل دیتاگریدویو و باتن ها کار کردم فضاش خیلی کم رفت بالا)

    مشکلش را در بالا گفتم .


    نقل قول نوشته شده توسط meysamabdolahi مشاهده تاپیک
    مرحله دوم :
    نکته بعدیش اینه وقتی که فرم رو میبندم از اون فضایی که اشغال میکنه 20 کیوبایت رو کم میکنه. یعنی همرو آزاد نمیکنه.

    همونجور که توضیح دادم وقتی هنوز فرم 3 رو فراخوانی نکرده باشم ، حجم اشغال شده 9 مگابایت هست، وقتی فرم 3 رو فراخوانی کردم حجم اشغال شده میشه 12 مگابایت و موقع خروج 3 مگابایت رو آزاد نمیکنه. برای این نشکل چه راه حلی پیشنهاد میکنین؟

    این هم مشکلش همون هست .
    منتها دقت کنید که خیلی از چیزها ، حافظه را اشغال میکنن که کلا جزء برنامه تون ممکنه حساب بشه از جمله clr ئه برنامه و ... .



    نقل قول نوشته شده توسط meysamabdolahi مشاهده تاپیک
    و یک سوال دیگه این که :



    چجوری میتونم اشاره گر ها رو null کنم؟ منظورتون همون SqlDataAdapter ، Data Table و SqlConnection هست ؟ ممنون میشم توضیح بدین. مرسی که وقت گذاشتین.
    اشاره گر ، null شدنی نیست .
    متغییرها ، null شدنی هستن . اگه متغییرها null بشن ، اشاره گرشون به شی مورد نظر را از دست میدن .
    منظورم ، هر شی ای که اینترفیس IDisposable را پیاده سازی کرده باشه که در نتیجه متد Dispose داره ، هست . از شی SqlDataAdapter گرفته تا Form و کنترل ها و ... .

    اگه باز درست نشد ، ممکنه جایی را برای همین روالی که توضیح داده شد ، برای شی یا اشیاهای دیگه اشتباه کرده باشین که میتونین از برنامه ی مدیریت حافظه ی ویژال استودیو کمک بگیرین .

  8. #8

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    نقل قول نوشته شده توسط SajjadKhati مشاهده تاپیک
    سلامی مجدد

    this ، اشاره گر به شی Form_3 تون هست دیگه . درسته؟
    طبعا شیِ Form_3 تون را هم در رویداد دکمه ای که در پست 1 گفته بودید ، خودتون شیِ جدید بهش دادین (new Form_3() کردین) دیگه . درسته؟
    اگه درسته ، در این حالت ، اینکه متد Dispose اش را فراخونی کردین ، درسته .
    اما اگه این ، شی ای بود که توسط کدهای ویژال استودیو نوشته میشد (یعنی خودتون مستقیما شی ایجاد نمیکردید و new نمیکردید) ، لازم نبود متد Dispose را فراخونی کنید .هر چند ، در این حالت هم اشکال چندانی هم نداشت .


    - دوما ، جای مناسب فراخونیِ متد Dispose ، توی رویدادِ خود اون شی یا کنترل زیر مجموعه های اون شی نیست . یعنی رویداد Form Close ئه Form_3 ، جای خوبی برای فراخونی متد Dispose نیست .
    جای مناسب اش ، بعد از اتمام کارش هست . یعنی بعد از اینکه متد Form_3_ShowDialog را فراخونی کردین ، بعد از این متد ، فراخونی متد Dispose ئه Form_3 ، بهترین جاش هست .
    راحت تر هست براتون که Form_3 را توی دستور using بذارید تا مجبور نباشید متد Dispose را فراخونی کنید .


    - سوما ، GC.Collect ، ای که در رویداد form close ئه Form_3 نوشتید ، هیچ تاثیری در پاک کردن داده های Managed ئه Form_3 در اینجا نداره :
    چون اولا شما در رویداد form close ئه Form_3 هستید و هنوز دارید از شیِ Form_3 استفاده میکنید .
    دوما و مهمتر اینکه شما تا اون موقع ، قطعا اشاره گر به شیِ Form_3 را null نکردین و از بین نبردین و قطعا تا اون موقع ، حداقل یک اشاره گر ، به شیِ Form_3 تون داره اشاره میکنه چون رویداد form close ئه Form_3 در حال اجرا شدن هست .

    باید همه ی متغییرهایی که به اون شی اشاره میکنن را اول ، null کنید تا هیچ اشاره گری به اون شی اشاره نکنه و بعدش متد GC.Collect را اجرا کنید .
    جای فراخونی این متدِ GC.Collect هم بعد از فراخونی متد Dispose (یا بعد از دستور using) ، اول ، همه ی متغییرهایی که به اون شی از Form_3 اشاره دارن را null میکنید و بعد از null کردنِ همه شون ، حالا متد GC.Collect را فراخونی میکنید (که در همون رویداد دکمه ای که در پست 1 گفتین ، میشه) .
    ضمنا ، با فراخونی این متد ، شما صرفا درخواست پاک سازی دادید . نه اینکه در همون لحظه پاکسازی انجام میشه .


    - چهارما ، دقت کنید که همه ی کنترل ها و کلا همه ی اشیاهایی که خودتون در کدنویسی ، مقدار جدید بهشون دادین را هم این کار را انجام بدین براشون .
    فرضا ممکنه در یک رویدادی در Form_3 ، یک Button ای را شی جدید داده باشید که در این صورت وظیفه ی شماست که بعد از استفاده ، متد Dispose اش را فراخونی کنید . همچنین حتی برای اینکه حافظه ی Managed اش را آزاد کنید ، بعد از اون ، فرضا اگه در متغییر سراسری تعریف کردید ، وظیفه ی شماست که اول ، null اش کنید و بعد متد GC.Collect را فراخونی کنید .
    همچنین هر شی دیگه ای (نه فقط کنترل ها) .




    مشکلش را در بالا گفتم .





    این هم مشکلش همون هست .
    منتها دقت کنید که خیلی از چیزها ، حافظه را اشغال میکنن که کلا جزء برنامه تون ممکنه حساب بشه از جمله clr ئه برنامه و ... .





    اشاره گر ، null شدنی نیست .
    متغییرها ، null شدنی هستن . اگه متغییرها null بشن ، اشاره گرشون به شی مورد نظر را از دست میدن .
    منظورم ، هر شی ای که اینترفیس IDisposable را پیاده سازی کرده باشه که در نتیجه متد Dispose داره ، هست . از شی SqlDataAdapter گرفته تا Form و کنترل ها و ... .

    اگه باز درست نشد ، ممکنه جایی را برای همین روالی که توضیح داده شد ، برای شی یا اشیاهای دیگه اشتباه کرده باشین که میتونین از برنامه ی مدیریت حافظه ی ویژال استودیو کمک بگیرین .
    خیلی خیلی ممنونم ازت سجاد جان. خیلی کاربردی بود. ممنونم از لطفت.

    قسمت اول توضیحاتتون : من فقط توی فرم 2 یه دکمه گذاشتم برای فراخوانی فرم 3 که اطلاعات توش نمایش میده
    الان طبق چیزایی که گفتین اومدم یه سری تغییرات دادم :
    1. توی Form2 یه دکمه ای داشتم که تو رویدادش این کد رو نوشتم برای فراخوانی Form3 :

    using (var frm3 = new Form3())
    {
    frm3.ShowDialog();
    frm3.Dispose();
    GC.Collect();
    }


    GC.Collect(); رو در رویداد form closing فرم 3 کلاً پاک کردم.
    تا اینجا درست هست؟

    چجوری میتونم اشاره گر به شیِ Form_3 را null کنم؟
    گفتید که : همه ی متغییرهایی که به اون شی از Form_3 اشاره دارن را null میکنید.
    منطورتون همون frm3 رو باید null کنم ؟؟

    - چهارما ، دقت کنید که همه ی کنترل ها و کلا همه ی اشیاهایی که خودتون در کدنویسی ، مقدار جدید بهشون دادین را هم این کار را انجام بدین براشون.

    منظورتون چی بود که گفتین این کار ها رو باید براشون انجام بدم؟ یعنی بیام تو هر رویداد Dispose کنم و GC.Collect رو فراخوانی کنم ؟ میشه یه مثال بزنید؟

    ممنون از پاسخگویی و صبورتیون.

  9. #9

    نقل قول: جلوگیری از افزایش مقدار حافظه در سی شارپ

    نقل قول نوشته شده توسط meysamabdolahi مشاهده تاپیک
    خیلی خیلی ممنونم ازت سجاد جان. خیلی کاربردی بود. ممنونم از لطفت.

    قسمت اول توضیحاتتون : من فقط توی فرم 2 یه دکمه گذاشتم برای فراخوانی فرم 3 که اطلاعات توش نمایش میده
    الان طبق چیزایی که گفتین اومدم یه سری تغییرات دادم :
    1. توی Form2 یه دکمه ای داشتم که تو رویدادش این کد رو نوشتم برای فراخوانی Form3 :

    using (var frm3 = new Form3())
    {
    frm3.ShowDialog();
    frm3.Dispose();
    GC.Collect();
    }


    GC.Collect(); رو در رویداد form closing فرم 3 کلاً پاک کردم.
    تا اینجا درست هست؟
    سلامی مجدد
    متد frm3.Dispose(); تون در کد بالا دیگه نیازی نیست . چون با اتمام بلاکِ using در کد بالا ، بصورت اتوماتیک این متد فراخونی میشه .
    این متد را از کد بالا پاک کنید .


    چون در بلاک using گذاشتین ، طبعا بعد از این بلاک ، دیگه متغییر frm3 تون در دسترس نخواهد بود . پس بعد از این بلاک ، نیازی به null کردن این متغییر هم ندارید .


    متد GC.Collect را در کد بالا ، درون بلاک using گذاشتین . یعنی زمانی که هنوز متغییر frm3 ، اشاره گر به شی داره و بهش نیاز هست .
    این متد را بعد از بلاک using استفاده کنید .

    البته باید دقت کنید که همه ی اشاره گر به اون شی را باید قبل از GC.Collect ، از بین برده باشید . فرضا ممکنه درون همین بلاک (یا حتی در هر متد و در هر کلاس دیگه) ، شیِ frm3 را درون متغییر سراسریِ دیگه (یا حتی درون متغییر محلی دیگه) ریخته باشین که قبل از فراخونی GC.Collect ، باید null شون کنید یا مطمئن از این باشید که همه ی اون متغییرها ، اشاره گرشون را از دست داده باشن .

    البته گاها در بعضی از جاها دیدم که بجای GC.Collect ، از ترکیب زیر هم استفاده میکنن :


    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();


    متد WaitForPendingFinalizers ، احتمالا نخ جاری را منتظر میذاره تا کارهای آزادسازی حافظه تمام بشه .
    دقیق هم متوجه نشدم که چرا قبل و بعد از این متد ، دو بار متد Collect را فراخونی میکنن . یاد هم پیگیری نکردم .

    نقل قول نوشته شده توسط meysamabdolahi مشاهده تاپیک
    چجوری میتونم اشاره گر به شیِ Form_3 را null کنم؟
    گفتید که : همه ی متغییرهایی که به اون شی از Form_3 اشاره دارن را null میکنید.
    منطورتون همون frm3 رو باید null کنم ؟؟

    چون از using استفاده کردید ، متغییری که برای اون using بکار بردین (متغییر frm3) را نه میتونید و نیازی هست که null کنید . چون بعد از بلاک ، اشاره گرش را از دست میده و قابل دسترس نیست .


    نقل قول نوشته شده توسط meysamabdolahi مشاهده تاپیک
    منظورتون چی بود که گفتین این کار ها رو باید براشون انجام بدم؟ یعنی بیام تو هر رویداد Dispose کنم و GC.Collect رو فراخوانی کنم ؟ میشه یه مثال بزنید؟

    ممنون از پاسخگویی و صبورتیون.
    در همین کدی که در بالا مثال زدید (یعنی کد و متغییر frm3 در بالا) ، مگه خودتون یه شی جدید در این کد بهش ندادید؟ (با new ، شی جدیدی به متغییر frm3 در این کد دادید) .
    خوب حالا وظیفه ی شما بود که متد Dispose اش را فراخونی کنید . البته بجای این کار ، از using استفاده کردید که بعد از اتمام بلاک اش ، خودش بصورت اتوماتیک ، این کار را انجام میده و نیازی به این فراخونی بصورت صریح توسط شما نداره ولی به هر حال خودتون با استفاده از using ، این کار را کردید .
    null کردن متغییر هم بستگی به شرایط خودتون داره ولی اغلب ، لازم نیست . مگر اینکه فرضا در متغییر سراسری استفاده کرده باشید و بخواید شی اش را از حافظه پاک کنید .


    ================================


    باز تاکید میکنم که این کار (استفاده از متد GC.Collect برای پاک سازی حافظه) ، در اغلب اوقات لازم نیست .
    مخصوصا برای چیزهایی که جم کم که فرضا زیر 100 مگابایت هست ، بگیره . چه برسه به 3 مگابایت .


    در لا به لای کدهای شما که اجرا میشه ، هر وقت GC خودش تشخیص بده یا هشدار پر شدن توسط سیستم عامل داده بشه ، GC خودش بصورت اتوماتیک این کار را انجام میده اون هم معمولا فقط برای نسل خاصی این پاک سازی را انجام میده .


    هر چند این مثال خوبی نیست اما فرضا یه فرم (فرضا همین فرم 3 تون) را در یه حلقه ی 100 تایی ایجاد کنید (و 500 میلی ثانیه بعد از اجرای فرم 3 ، اون را ببندید) . یعنی 100 بار پشت سر هم ، این فرم تون اجرا و بعدش بسته بشه . خودتون هم اون کد GC.Collect را حذف کنید و اجراش نکنید .
    در این حالت ، به پنل Diagnostic Tools و نمودار قسمت Process Memory نگاه کنید ، ببینید چند بار روی این نمودار ، علامت و آیکونِ فِلِشک زرد رنگ زده که نشونه ی اجرای متد GC.Collect توسط GC هست .





    3 علامت زرد رنگ در قسمت پایین شکل بالا که بصورت خودکار و بدون فراخونی GC.Collect در کدنویسی ، و توسط GC بصورت خودکار اون هم در نسلی که خودش به صلاح میدونه ، اجرا شد .


    بنابراین در اغلب اوقات ، شما هم اگه جداگانه این متد را فراخونی کنید ، بسته به شرایط داره اما ممکنه قبل اش خود GC این کار را کرده باشه و بنابراین فراخونی شما ، چندان تاثیر خاصی روی کم کردن حافظه ی بدون استفاده و بدون اشاره گر ، نداشته باشه که معمولا (نه همیشه) این طوره . واسه ی همین بود که گفتم پیشنهاد نمیشه این کار .


    اگه میبینید که فرضا مقدار حافظه ای که حتی بعد از فراخونی این متد ، بیشتر از قبل از استفاده ی اون کد شد و به اولش بازنگشته (فرضا ، اول و قبل از اجرای فرم 3 ، حافظه ی اشغالی برنامه تون 15 مگابایت بوده و بعد از اجرا و بستن فرم 3 ، و فراخونی حتی GC.Collect ، فرضا 16 مگابایت شده و به مقدار اولیش برنگشته) ، ممکنه بخاطر خیلی چیزها باشه .

    فرضا ممکنه بخاطر این باشه که بخش قابل توجهی از داده ها ، بین برنامه و حتی فراتر از برنامه (برای چندین برنامه یا سرویس یا پروسه) ، به اشتراک گذاشته میشن که این اطلاعات به اشتراک گذاشته شده ، معمولا پاک نمیشن .
    و مسایل دیگه که نمیدونم و خواستین میتونین تحقیق کنین .

    اگه پروژه تون و برنامه تون را در خود ویژال استودیو را هم چندین بار اجرا کنید (f5 را بزنید) و هر بار ببندید ، در هر چند بار اجرا ، متوجه میشید که مقدار حافظه ی اشغالی در task manager برای پروسه های ویژال استودیو ، بیشتر میشه (فرضا هر 5 بار ، اندکی افزایش پیدا میکنه) .
    مثلا برنامه ی wpf ام در vs 2022 (با resharper) ، هر 3 بار که اجرا میکنم و میبندم ، حدود 100 مگابایت بر حجم قبلی ویژال استودیو ، اضافه میشه . یعنی اگه 30 بار برنامه را اجرا و ببندم ، حدود 1 گیگ به حجم ویژال استودیو اضافه میشه .

    به هر حال در اغلب حالات ، نیازی به فراخونی متد GC.Collect توسط برنامه نویس مخصوصا در کارهای حجم پایین نیست .
    معمولا این کارها را وقتی دیتابیس خیلی سنگین و مخصوصا وقتی فایل حجیم (فرضا ، حداقل بیش از 100 مگابایت) را میخونن و کارشون که تمام شد اما میخوان مطمئن بشن که حافظه خالی شد (اون هم باز هم چندان شاید توصیه نشه) ، این کار و این متد را فراخونی میکنن .

    ==========

    قبلا استادم بهم برای این کار که میخواستم کنم ، اولا شدیدا توصیه میکردن که این کار را نکنم (اون هم نه مثل این حالتی که شما تجربه میکنید که در حد چند مگابایت هست . بلکه فایلی را میخوندم که اگه اشتباه نکنم حدود 700 مگابایت بود که حالا بعد از استفاده ، حافظه همون مقدار باقی مونده بود که نمیدونم شاید بخاطر این کارهایی که اون موقع انجام نداده بودم یا ترتیب اش را رعایت نمیکردم و یا حتی خود GC این تشخیص را داده بود که در اون موقع ، هنوز اجرا نکنه یا به هر حال ، چون سال ها قبل بود و دقیق ، جزئیاتش یادم نمیاد) .

    اون موقع استادم که مثال زدند برای انجام ندادن چنین کاری این بود که اولا GC ، هر وقت به صلاح بدونه ، این کار را خودش انجام میده (مثل عکس بالا که خودش انجام داد) ؛ میگفتن مثل این هست که ماشین تون کثیف بشه و بخواید کارواش ببرین . اولا تا زمانی که کارواش هست ، نمیتونید ازش استفاده کنید (هر چند ، زمان کارواش نسبت به زمان هایی که داریم از ماشین استفاده میکنیم ، خیلی کمتر باشه . روی همون آیکون های زرد رنگ که مربوط به این کد پاکسازی حافظه هست ، موس را نگه دارین ، میگه که چند میلی ثانیه برای اجرای هر کدوم زمان برد) .

    دوما میگفتن که این کارم مثل این میمونه که ماشین را بعد از اینکه کارواش بردم ، باز بعد از یک دقیقه ی بعد ، باز ممکنه کثیف بشه و دوباره بعد از یک دقیقه ، مجددا کارواش ببرم . حتی زمانی که خود کارواش داره ماشین را میشوره ، اگه ذره بین بگیریم ، باز جای دیگه ای از ماشین ممکنه کثیف بشه چه برسه به چند دقیقه یا چند ساعت یا چند روز بعد .
    و این دلیل نمیشه که چون با ذره بین ، چند دقیقه ی بعد ، فلان جا کثیف شد ، پس ، چند دقیقه ی بعد ، مجددا ماشین را به کارواش ببریم .
    البته نقل به مضمون شون این بود .

    چون GC ، خودش هر موقع صلاح بدونه ، این کار را میکنه .
    البته واسه ی من فرق داشت (حالا اینکه حافظه ای که در اثر خوندن فایل برام اون موقع اشغال شد و پاک نکرد ، شاید تقصیر من بود اون موقع ، نمیدونم) ولی به هر حال من نیاز داشتم که خودم این کار را کنم و شاید در این شرایط من ، که شرایطی هست که کم پیش میاد ، شاید کار درستی میبود .
    نه در شرایط شما در حد چند مگابایت .
    عکس های ضمیمه عکس های ضمیمه
    • نوع فایل: jpg 1.JPG‏ (22.0 کیلوبایت, 26 دیدار)

تاپیک های مشابه

  1. مبتدی: اموزش ساخت قالب فارسی و ریسپانسیو وردپرسی رو کسی داره ؟
    نوشته شده توسط mohammadreza65 در بخش PHP
    پاسخ: 4
    آخرین پست: چهارشنبه 26 آبان 1400, 10:55 صبح
  2. پاسخ: 0
    آخرین پست: چهارشنبه 30 بهمن 1392, 09:31 صبح
  3. سورس فارسی نویس، نوشتن فارسی در برنامه هایی که زبان فارسی رو پشتیبانی نمیکنند
    نوشته شده توسط سید حمید حق پرست در بخش برنامه نویسی در 6 VB
    پاسخ: 6
    آخرین پست: چهارشنبه 02 بهمن 1392, 10:00 صبح
  4. سوالی در مورد متنهای فارسی و ادیت فارسی در گوشیهای که فارسی پشتیبانی نمیکنند
    نوشته شده توسط Mehran_Asghari در بخش Java ME : نگارش میکرو جاوا
    پاسخ: 3
    آخرین پست: شنبه 21 بهمن 1385, 17:37 عصر

برچسب های این تاپیک

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •