پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
نقل قول:
پروژه رو که تو پست اول توضیح دادم
یه بازی آنلاین هست که باید توش تصویر حدس زد و به این صورته که یه مستطیل تقریبا سیاه هست (کد رنگش تو کدهام هست) که دایره توش هست از داخل دایره قسمتی از یه تصویر پیداست و این دایره مرتب توی مستطیل دور میزنه
حالا من تصویر این مستطیل رو از طریق برنامه ی manycam که وب کم مجازی هست دارم و این تصویر رو از طریق کتابخونه ی emgu.cv که کدهاش توی نت بود به C#.net اوردم
تا اینجا که مشکلی نیست ok
یعنی بخاطر رسم یه مستطیل ، از یه کتابخونه ای که به وب کم ربط داره ، استفاده کردید؟!!
نمیدونم منظورتون همینه و یا من بد متوجه شدم.
اگه همینه ، از شیِ Graphic میتونید همین کار را کنید . نیازی به استفاده از کتابخونه ی وبکم نیست!!
اگه گرافیک یا برنامه نویسی را کار نکردید و میخواید یه پروژه ی گرافیکی درست کنید ، قطعا یا شدنی نیست یا با مشکلات بسیار زیاد مواجه میشید . اگه این طوره ، حتما اول برید یاد بگیرید .
منظورم ، توصیف پروژه نبود . کد پروژه بود که خودتون باید تمام زوایاش را بررسی کنید .
نقل قول:
حالا این تصویر به خاطر اینکه همیشه بکگراندش یک رنگ هست میتونم بکگراندش رو transparent کنم و نهایت دایره میمونه که قسمتی از تصویر که باید حدس زده بشه توش مشخص هست (توی عکسی که فرستادم یه خرمالو هست)
برای هر فریم باید این کار انجام بشه و کدهای نمایش وب کم توی پیکچر باکس باید توی تایمر باشه چون emgu.cv در هر لحظه فقط یه فریم کپچر میکنه. خوب در نهایت مجموع تمام فریمها میشه تصویر مورد نظر. به همین سادگی
راستش من برنامه نویسی رو در حد دانشگاه بلدم رشتم نرم افزار بوده :1. (28):
****************************
کد های بدون استفاده رو پاک کردم
اومدم کدهای ترنسپرنت رو هم پاک کردم فقط این کد رو گذاشتم
کد:
Capture capture = new Capture();
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox2.Visible = false;
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
}
}
بازم حافظه سریع پر شد یعنی خود نمایش تصویر توی پیکچر باکس هم حافظه رو پر میکنه
میشه یه مثال توی کد خودم در مورد dispose بزنید؟
مثال ، که در کد خودتون هم هست .
وقتی نوشتید :
using (var nextFrame = capture.QueryFrame())
، وقتی که کدِ بلاکِ using ، بسته شه ، هر منبعِ unmanaged ای که برای شیِ nextFrame در نظر گرفته شده بود ، از حافظه ، پاک میشه .
فرقی نداره که بجای استفاده از using در کد بالا ، شما متدِ dispose ئه شیِ nextFrame را فراخونی کنید . یعنی فرقی نداره که بجای کد بالا ، از nextFrame.Dispose() استفاده کنید (البته یه فرق خیلی کوچولو داره) .
اما فراخونیِ متدِ Dispose (یا استفاده از using) ، بسته به کار خودتون داره که چه زمانی کارتون با اون شی ، به اتمام رسید . اگه قبل از اتمام ، Dispose کنید ، امکان زیادی داره که زمان استفاده از شیِ مورد نظر ، با مشکل (و ارور زمان اجرا یا درست عمل نکردنِ شی و هر مشکل دیگه ای) مواجه بشید .
اون شیِ capture ، شی ای Dispose شدنی هست که زمانی که کارتون باهاش تمام شد ، باید Dispose اش کنید (که خودتون میدونید ، چه زمانی کارتون باهاش تمام میشه) .
اینکه رم تون هنوز پر میشه ، قبلا اشاره کردم .
Image ها هم Dispose شدنی هستند .
در pictureBox1.Image ، یه Image ئه جدیدی را در هر بار اجرای تایمر ایجاد میکنید که در اجرای بعدی ، Image های قبلی ای را که ایجاد کرده بودید ،در حافظه میذارید باقی بمونه و Dispose شون نمیکنید .
ضمن اینکه برای پاک کردنِ سریعترِ حافظه های managed هم (که قبلا گفته بودم) ، از متد GC.Collect() استفاده نکردید .
1 :تعداد فایل پیوست
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
نقل قول:
یعنی بخاطر رسم یه مستطیل ، از یه کتابخونه ای که به وب کم ربط داره ، استفاده کردید؟!!
خیر، درسته این کتابخونه برای پردازش تصویر هست اما من فقط تصویر وب کم خودم رو توی یه پیکچر باکس نمایش میدم همین
تصویر من، تصویر یه بازی آنلاین هست که یه کادر مستتطیل شکل هست. فرض کنید دارید از مانیتور کامپیوتر فیلم میگیرید همین
الان یه چیزی متوجه شدم اینکه حافظه اشغال میشه اما به یه حدی که رسید دوباره خالی میشه
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
حالت عادی روی 64 هست و موقع اجرای برنامه تا 79 میرشه و دوباره برمیگرده 64، این عادی هست؟
و اون موقع ارور داده بود چون رم من حدود 85 درصد پر بود و برنامه رو که اجرا کردم پر شد.
من از dispose استفاده کردم اما هیچ تاثیری نداشت
این دو خط رو به تایمر اضافه کردم
کد:
myBitmap3.Dispose();
pictureBox1.Dispose();
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
نقل قول:
خیر، درسته این کتابخونه برای پردازش تصویر هست اما من فقط تصویر وب کم خودم رو توی یه پیکچر باکس نمایش میدم همین
تصویر من، تصویر یه بازی آنلاین هست که یه کادر مستتطیل شکل هست. فرض کنید دارید از مانیتور کامپیوتر فیلم میگیرید همین
الان یه چیزی متوجه شدم اینکه حافظه اشغال میشه اما به یه حدی که رسید دوباره خالی میشه
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
حالت عادی روی 64 هست و موقع اجرای برنامه تا 79 میرشه و دوباره برمیگرده 64، این عادی هست؟
و اون موقع ارور داده بود چون رم من حدود 85 درصد پر بود و برنامه رو که اجرا کردم پر شد.
منظورتون اینه که بصورت پیش فرض ، برنامه تون از 64 مگابایت از رم استفاده میکنه؟
این ربطی به اصولی بودن کدتون نداره .
برنامه تون ممکنه 40 مگ (یا کمتر) از رم را اشغال کنه اما کدی نوشته باشین که یه متغییر و شی ای را تعریف کرده باشه اما زمانی که ازش استفاده نمیکنین و یا حتی بعد از بستنِ برنامه تون ، حافظه ای که براش گرفته شده را به سیستم عامل ، پس نده و کماکان اشغال کنه .
که جریانش (جریان آزادسازی حافظه های unmanaged) را توضیح دادم .
نقل قول:
من از dispose استفاده کردم اما هیچ تاثیری نداشت
این دو خط رو به تایمر اضافه کردم
کد:
myBitmap3.Dispose();
pictureBox1.Dispose();
نگفتم که استفاده از Dispose ، اون میزان از آزادسازی ای از رم که مد نظرتون هست ، تاثیر داره یا تاثیر نداره .
Dispose ، باعث میشه منابع حافظه که برای حافظه های نوع unmanaged (نه همه ی نوع حافظه که شامل managed هم میشه) برای اون شی استفاده میشه ، از حافظه ، آزاد بشه .
مقدار این حافظه ی unmanaged برای اون شی ، میتونه در حد چند بایت باشه ، یا در حد کیلو یا شاید مگا یا گیگابایت . مقدار حافظه ی unmanaged برای اون شی را فقط کسی که کتابخونه اش را ساخت ، میدونه .
وظیفه ی شما به عنوان برنامه نویس فقط اینه که اگه شیِ جدیدِ Dispose شدنی ای را به متغییری اختصاص دادین ، بعد از اتمام کارتون با اون متغییر ، این متد را فراخونی کنین تا منابع حافظه ی unmanaged اش از حافظه ، پاک شه . اما اینکه چه حجمی از حافظه ی unmanaged ، به این شی اختصاص داده شده بود ، فقط به کسی که کتابخونه اش را نوشت ، مربوطه .
درباره ی آزادسازیِ سریعترِ منابع managed (ای که اشاره گری بهش اشاره نمیکنه) هم که گفتم .
با این حال ، اینها ، این مقادیر را از حافظه پاک میکنن . نه صرفا از حافظه ی فیزیکی (رم) . بلکه برنامه ها از حافظه ی مجازی استفاده میکنن (شامل هم رم و هم pagefile ئه حافظه ی جانبی) .
اگه فرضا تغییرات حافظه را از قسمت نمودار memory در task manager پیگیری میکنید ، اون نمودار فقط تغییرات حافظه ی فیزیکی (رم) را نشون میده .
-----------------
دقت کنید که pictureBox1 را (مثل همه ی اشیاء دیگه) ، زمانی Dispose کنید که :
- اولا ، خودتون یه شیِ جدیدی از pictureBox ساخته باشید . یعنی زمانی که خودتون (new PictureBox را نوشته باشید) .
یعنی زمانی که pictureBox را زمانی که فرم را طراحی میکردید (زمانِ design در form) ، اضافه کردید ، برای این نوع pictureBox ، نیازی به Dispose کردن ، نیست .
- و دوما به کنترلِ pictureBox1 ، نیازی ندارید . یعنی فرضا میخواید pictureBox1 را از روی form تون حذف کنید . یا اینکه میخواید از برنامه بیرون برید .
بنابراین اگه احتمالا زمان طراحی فرم ، pictureBox1 را اضافه کردید (که احتمالا همینطوره) ، نیازی به اجرای کدِ pictureBox1.Dispose() نیست .
و همچنین ، زمانی شیِ myBitmap3 را هم Dispose کنید که دیگه در جای دیگه ای ازش استفاده نمیکنید و لازم تون نمیشه .
یعنی مثلا زمانی شیِ myBitmap3 را هم Dispose کنید که در pictureBox1.Image (یا هر جای دیگه) ، دیگه از شیِ myBitmap3 استفاده نمیکنید .
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
اون تصویر که مقدار رم رو نشون میده تصویر برنامه hwinfo است که مقدار اشغال شده رو به درصد نشون میده یعنی 64 درصد که چون رم من 8 گیگ هست میشه حدود 5 گیگ
آقا من چون مثل شما زیاد تخصصی نیستم اودم با آزمون خطا پیدا کردم
یه کد رفرش فرم زدم
دیم که اصلا از 60 بالا نمیره!
به نظزتون چطور میتونم هندلش کنم
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
نقل قول:
اون تصویر که مقدار رم رو نشون میده تصویر برنامه hwinfo است که مقدار اشغال شده رو به درصد نشون میده یعنی 64 درصد که چون رم من 8 گیگ هست میشه حدود 5 گیگ
برنامه ی hwinfo چرا؟!!
شما باید برنامه ی خودتون را دقیق رصد کنید که چه نوعی ، فعلا داره چه مقدار حافظه را مصرف میکنه .
در ویژال استودیو ، از قسمت Memory Usage در Diagnostic Tools ، باید snapshot بگیرید تا متوجه بشید .
snapshot را هم حداقل 2 بار باید بگیرید . یک بار break point را قبل از اینکه کد مورد نظرتون (که از رم زیادی استفاده میکنه) ، بذارید و snapshot بگیرید و بار دوم ، f10 را بزنید تا اجرای کد ، به کدهای مورد نظرتون (که رم بالایی را استفاده میکنن) ،برسه و دومین snapshot را بگیرید و مقدار حافظه ی تمام اشیاءِ اون نوع را مقایسه کنید :
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
و
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
دقت کنید که در snapshot ، صرفا اطلاعات مقدار حافظه ای که برای تمامِ اشیاهایی از برنامه تون ، از یک نوعِ خاصی هست (مثلا تمام اشیایی که از نوع Bitmap هست) را بهتون میده .
برای جستجوی نوع داده (گرفتنِ مقدار حافظه ی اشغالی برای تمام اشیایی که از اون نوع هست) هم وقتی روی لینکِ snapshot ای کلیک کردید و به تصویرِ زیر رسیدید (که در لینک اول در بالا که گذاشتم ، توضیح میده) ، یه کادرِ جستجو ، در قسمت بالا ، سمت راست صفحه داره که میتونید نامِ نوعِ تمام اشیایی از اون نوع که در کل برنامه تون وجود داره را جستجو کنید که چقدر از حافظه مصرف میکنن (فرضا نوعِ Bitmap یا نوعِ Image را در این کادر میتونید بنویسید) (کادر در تصویر زیر مشخص هست) :
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
نقل قول:
آقا من چون مثل شما زیاد تخصصی نیستم اودم با آزمون خطا پیدا کردم
یه کد رفرش فرم زدم
دیم که اصلا از 60 بالا نمیره!
به نظزتون چطور میتونم هندلش کنم
ربطی به حافظه ی اشغالی برنامه تون نداره .
اگه this ، شیِ فرم تون هست ، فرم تون را فقط ریفرش میکنه (نه کار دیگه ای) .
ممکنه در این لحظه ، گربگ کالکتور هم بخواد داده های managed را هم collect کنه (که قبلا بهتون گفتم که چجوری با کد این کار را کنید) .
به هر حال ، این کد ربطی به حافظه نداره .
-------------
لطفا اول کد نویسی سی شارپ را طبق منبعی که دادم (فیلم آموزش سی شارپ یا منابع انگلیسی) و همچنین کتابخونه های مورد نظرتون را (مثل گرافیک ، یا اون کتابخونه ای که برای وبکم بود و ...) که باز هم منابع یادگیری گرافیک (فیلم آموزش) را دادم ، اول کامل یاد بگیرید . بعد از یادگیری ، مشکلاتی که براتون بوجود میاد را بپرسید .
این طور که نمیشه بدون یادگیری دقیق بخواید برید سروقت پروژه . بسیاری سئوالات (از مبتدی گرفته تا بالاتر) براتون پیش میاد که با یادگیری زبان سی شارپ و کتابخونه ها ، این سئوالات از همون ابتدا براتون توجیه و قابل حل میشه .
پست قبلی (پست 13) ام را هم ویرایش کردم (بعد از خط چین) ، بخونید .
تاپیکی که اسمش را "شارپ کردن تصویر در c#" گذاشتید ، این انجمن ، با کاراکترهایی مثل # و اینها ، مشکل داره . واسه ی همین تاپیک تون نمایش داده نمیشه . بجای c# ، صرفا سی شارپ بنویسید (کلا کاراکتر # نداشته باشه) .
2 :تعداد فایل پیوست
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
برنامه hwinfo از قبل نصب بود و کلا همیشه دارمش
همونطور که بهتون گفتم حتی کد نمایش وب کم تو پیکچر باکس که همون چند خط اول هست رو به تنهایی هم بزنم حافظه زیاد میبره. حافظه رو با روش شما چک کردم و هر بار 867 مگ حافظه میگیره و دوباره ازاد میشه! اگه چند خط کد بیت مپ رو اضافه کنم که ترنسپرنت کنم و چاپ کنم رو فرم هر بار 1.9 گیگ حافظه میگیره دوباره آزاد میکنه! که فکر میکنم زیاد هست چون من حساب کردم چون دوربینم 60 فریم داره و تایمر هم 17 میلی ست شده یعنی هر ثانیه حدود 60 فریم ثبت میشه توی پیکچر باکس و چون 25 ثانیه طول برد تا حافظه آزاد شد پس 25*60= 1500 فریم توی پیکچر باکس ثبت شده که شده 867 مگ.
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
این عکس انالایز حافظه برای این کد هست
کد:
private void timer1_Tick(object sender, EventArgs e)
{
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
}
}
}
و میدونم الان میگید باید اسنپ شات میگرفتید اما گرفتم هیچ اشاره ای به هیچ چیز نکرده که شما گفتید مثلا بیت مپ یا پیکچر باکس من هرچه گشتم ندیدم، موجوده اگه گفتید اپلود میکنم
مگه شما نمیگید با استفاده از using بعد از اینکه کارش تمام شد حافظه رو آزاد میکنه الان فقط using تو کد هست ولی انگار فریم ها رو رو هم توی پیکچر باکس ذخیره میکنه و فریم قبلی رو پاک نمیکنه
من منظورم این نیست که این کد (()this.refresh)مدیریت حافظه میکنه اما دفدش کردن باعث میشه حافظه خالی بشه با همین کد بالا تست کردم به این صورت
کد:
private void timer1_Tick(object sender, EventArgs e)
{
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
this.Refresh();
}
}
}
نتیجه شد این
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
فقط 200 مگ حافظه نهایت
gc collector هم دارم سرچ میکنم
فقط الان راهی هست سریع بشه توی تایمر بعد از هر بار که پیکچرباکس یه عکس توش قرار گرفت خالی بشه؟
یه همچین چیزی
picturebox1.image=null;
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
آقا gc.collect() نوشتم عجب چیزیه
نمیزاره از 46 مگ میشتر بشه! :1. (31):
کد:
Capture capture = new Capture();
private void timer1_Tick(object sender, EventArgs e)
{
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
}
}
Bitmap myBitmap3 = new Bitmap(pictureBox1.Image);
Color pixle1 = myBitmap3.GetPixel(100, 100);
Color pixle2 = myBitmap3.GetPixel(400, 250);
if (pixle1 == Color.FromArgb(24, 53, 73) || pixle2 == Color.FromArgb(24, 53,73))
{
myBitmap3.MakeTransparent(Color.FromArgb(24, 53, 73));
gfx.DrawImage(myBitmap3, 1, 1);
GC.Collect();
}
else
{
GC.Collect();
}
}
فقط یه سوال البته میدونم زیاد سوال پرسیدم ببخشد شما رو هم اذیت کردم این gc.collect() چطور فریم هایی که توی فرم چاپ شدن رو پاک نمیکنه یعنی برنامه من هیچ ایرادی توش نیفتاد ولی حافظه خالی شد! ظاهرا اشغال حافظه مال همین عکس های چاپ شده توی فرم و توی پیکچرباکس هستن یا من اشتباه میکنم؟
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
نقل قول:
برنامه hwinfo از قبل نصب بود و کلا همیشه دارمش
همونطور که بهتون گفتم حتی کد نمایش وب کم تو پیکچر باکس که همون چند خط اول هست رو به تنهایی هم بزنم حافظه زیاد میبره.
سلام
من هم قبلا بارها گفتم .
کدِ زیرتون :
یه شیِ بیت مپ جدید ایجاد میکنه (که این شی را به pictureBox1.Image اختصاص دادید) .
هر بار هم در تایمر ، ازش استفاده میکنید .
اما در تایمرِ بعدی که از این شی استفاده کردید ، این شیِ بیت مپِ قبلی را گفتید فورا از حافظه پاک کنه؟
نه .
بنابراین این شی های بیت مپ ، تجمع میشه و رم تون پر میشه .
نقل قول:
حافظه رو با روش شما چک کردم و هر بار 867 مگ حافظه میگیره و دوباره ازاد میشه!
روش من چیه؟!!
من از خودم روشی ایجاد نکردم .
روال برنامه نویسی .net هست .
ببینید ، از هر شی ای بسازید و استفاده کنید (چه شیِ بیت مپ مثل کد بالا و هر شی ای) ، 2 حالت داره :
- حافظه ی managed ، برای اون شی اختصاص داده میشه .
- ممکنه هم علاوه بر این ، از حافظه ی Unmanaged هم استفاده بشه (این نوع اشیاء ، متد Dispose دارن) .
حالا برای پاک سازیِ هر نوع از این حافظه ها برای اون شی ، روشی متفاوت وجود داره :
- پاکسازی حافظه ی Unmanaged ، اغلب ، با متد Dispose انجام میشه .
- پاکسازیِ حافظه ی managed ، اول باید هیچ اشاره گری به اون شی ، اشاره نکنه و بعد اینکه با متد GC.Collect ، میتونین روند حذف حافظه های managed (ای که اشاره گری بهش وجود نداره) را درخواست بدین که در اولین فرصت این کار انجام بشه .
اگه از متد GC.Collect استفاده نکنین ، گربگ کالکتور ، این روند که پاکسازی حافظه های managed (ای که اشاره گری بهش وجود نداره) را میذاره برای وقتی که خودش به صلاح بدونه (مثلا موقعی که برنامه تون را میبندید یا زمانی که حافظه ی سیستم ، پر شده باشه و ...) . یعنی اگه از اون متد استفاده نکنین ، گربگ کالتور ، عجله ای در بررسی و آزادسازیِ حافظه های managed (ای که اشاره گری بهش وجود نداره) ، نمیکنه .
نقل قول:
اگه چند خط کد بیت مپ رو اضافه کنم که ترنسپرنت کنم و چاپ کنم رو فرم هر بار 1.9 گیگ حافظه میگیره دوباره آزاد میکنه! که فکر میکنم زیاد هست چون من حساب کردم چون دوربینم 60 فریم داره و تایمر هم 17 میلی ست شده یعنی هر ثانیه حدود 60 فریم ثبت میشه توی پیکچر باکس و چون 25 ثانیه طول برد تا حافظه آزاد شد پس 25*60= 1500 فریم توی پیکچر باکس ثبت شده که شده 867 مگ.
فاصله ی زمانی تایمر (که 17 میلی ثانیه گذاشتین) ، اولا که فکر نکنید دقیقا هر 17 میلی ثانیه اجرا میشه .
بلکه این فاصله ی زمانی ، حتی اگه پردازنده مشغول نباشه ، دقیق نیست . یعنی اجراش ،اندکی ممکنه جلو و عقب بشه .
اگه عواملی مثل اِشغالِ پردازنده هم وجود داشته باشه که احتمال داره تاخیرش بیشتر بشه .
اما در کل تاخیرش خیلی زیاد نیست .
ولی اگه برای زمان های طولانی بخواین روی فاصله ی زمانیِ تایمر ، حساب باز کنید ، این تاخیر خودش را کاملا واضح نشون میده . مثلا برای یکسان کردنِ رقص نور با آهنگی و یا برای هماهنگ کردن با فریم های فیلم ، هر چی فیلم و آهنگ طولانی تر باشن ، تاخیرش بیشتر خودش را نشون میده .
نقل قول:
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
این عکس انالایز حافظه برای این کد هست
کد:
private void timer1_Tick(object sender, EventArgs e)
{
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
}
}
}
و میدونم الان میگید باید اسنپ شات میگرفتید اما گرفتم هیچ اشاره ای به هیچ چیز نکرده که شما گفتید مثلا بیت مپ یا پیکچر باکس من هرچه گشتم ندیدم، موجوده اگه گفتید اپلود میکنم
اون لینکی که دادم ، گفته بود .
نمیدونم از نسخه ی چند از ویژال استودیو استفاده میکنید .
توی نسخه ی 2019 اش ، وقتی برنامه را اجرا کنید ، سمت راستِ ویژال استودیو ، پنجره ی Diagnostic Tools باز میشه . (اگه این پنجره نشون داده نشد ، از قسمت Debug > Windows > Show Diagnostic Tools انتخاب کنید) .
تقریبا قسمت زیرِ این پنجره ، سربرگِ Memory Usage را انتخاب کنید . روی آیکون دوربین که کنارش نوشته Take Snapshot کلیک کنید .
در ستون Heap Size ، روی عددی که در این ستون داده شد ، کلیک کنید .
در پنجره ی باز شده (شبیه تصویر در لینک 15) میاد که نوعِ مورد نظرتون را میتونید جستجو کنید . منتها قبل از جستجوی نوع مورد نظرتون ، کدِ اشیاء و متغییرهایی که از اون نوع هستن ، باید اجرا شده باشن . وگرنه در لیست نمیان (که بدیهی هست) .
نقل قول:
مگه شما نمیگید با استفاده از using بعد از اینکه کارش تمام شد حافظه رو آزاد میکنه
نه .
گفتم فقط حافظه های Unmanaged از اون شی را پاک میکنه . (اون هم خودش پاک نمیکنه ، درخواست پاک کردن را میده) .
نقل قول:
الان فقط using تو کد هست ولی انگار فریم ها رو رو هم توی پیکچر باکس ذخیره میکنه و فریم قبلی رو پاک نمیکنه
اولا که در کد بالای شما ، فقط برای شیِ nextFrame ، درخواستِ حذفِ حافظه های Unmanaged (ای که برای متغییرهاش اختصاص داده شد) را دادین .
حافظه ی managed را نگفتین که فوری حذف کنه . بنابراین پاک کردن حافظه ی managed ، میمونه تا وقتی که گربگ کالکتور صلاح بدونه که معمولا مواقع لزوم یا مواقع اضطراری هست .
دوما (همونطور که در بالا و هم در پست های قبل گفتم) ، شما هیچ کاری با شیِ خروجیِ متدِ زیر در کدتون نکردین :
نگفتین که حافظه ی Bitmap ای که در تایمر قبلی تولید شده بود را اولا نه حافظه ی Unmanaged اش را پاک کردین (چون متد Dispose از این شی را اجرا نکردین) و نه حافظه ی managed اشس را گفتین که فوری پاک کنه (زمانی که بهش نیاز ندارین) .
بنابراین اولا علاوه بر اینکه این شی را به پروپرتیِ pictureBox1.Image اختصاص میدین ، در متغییرِ دیگه ای از این نوع هم اختصاص بدین تا در تایمر بعدی که بهش نیاز ندارین ، Dispose اش کنید :
کد:
private Image previouseImageForDisposing;
private void timer1_Tick(object sender, EventArgs e)
{
if (this.previouseImageForDisposing != null)
{
this.previouseImageForDisposing.Dispose();
this.previouseImageForDisposing = null;
}
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
this.previouseImageForDisposing = pictureBox1.Image;
}
}
}
اون متغییر previouseImageForDisposing ، حتما باید null بشه تا اشاره گرش را از دست بده وگرنه با فراخونیِ متد GC.Collect ، شی اش (یا هر شی ای که اشاره گر داره) ، از حافظه پاک نمیشه .
دوما ، اون متد GC.Collect را باید اجرا کنید تا بگید حافظه ی managed از تمام اشیایی که اشاره گر ندارن ، در اولین فرصت ، پاک بشن (که این کار را هم نکردید) .
دقت کنید که حتما فراخونیِ متدِ GC.Collect را بعد از کدی که متغییرِ previouseImageForDisposing در بالا را null کردیم ، و همچنین بعد از کد زیر در بالا ، انجام بشه :
کد:
pictureBox1.Image = nextFrame.ToBitmap();
چون اشاره گرهای به شیِ Bitmap ئه قبلی (که پروپرتیِ pictureBox1.Image و متغییر previouseImageForDisposing که بهش اشاره میکردن) ، باید قبلش از دست بره .
لازم هم نیست حتما در هر تایمر ، متد GC.Collect را فراخونی کنید . البته مشکلی نیست و میتونین انجام بدین . اما بهتره که هر وقت حافظه ی کاربر نهایی پر شد یا از اشغال حافظه ، از مقدار خاصی بیشتر شد انجام بدین . چون برای پردازنده ، سربار داره (ولو سربارش ، اندک یا زیاد باشه) .
نقل قول:
من منظورم این نیست که این کد (()this.refresh)مدیریت حافظه میکنه اما دفدش کردن باعث میشه حافظه خالی بشه با همین کد بالا تست کردم به این صورت
کد:
private void timer1_Tick(object sender, EventArgs e)
{
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
this.Refresh();
}
}
}
نتیجه شد این
برای مشاهده این لینک/عکس می بایست عضو شوید !برای عضویت اینجا کلیک کنید ]
فقط 200 مگ حافظه نهایت
gc collector هم دارم سرچ میکنم
خالی نمیکنه .
شاید با ریفرش کردن ، فرصتی برای گربک کالکتور باشه یا گربگ کالکتور پیامی دریافت کنه که حافظه را اون موقع جمع کنه . مدیریت حافظه ی mmanaged ، فقط توسط گربگ کالکتور انجام میشه .
بالاخره روش اصولی نیست.
نقل قول:
فقط الان راهی هست سریع بشه توی تایمر بعد از هر بار که پیکچرباکس یه عکس توش قرار گرفت خالی بشه؟
یه همچین چیزی
picturebox1.image=null;
توضیح دادم .
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
نقل قول:
آقا gc.collect() نوشتم عجب چیزیه
نمیزاره از 46 مگ میشتر بشه! :1. (31):
کد:
Capture capture = new Capture();
private void timer1_Tick(object sender, EventArgs e)
{
using (var nextFrame = capture.QueryFrame())
{
if (nextFrame != null)
{
pictureBox1.Image = nextFrame.ToBitmap();
}
}
Bitmap myBitmap3 = new Bitmap(pictureBox1.Image);
Color pixle1 = myBitmap3.GetPixel(100, 100);
Color pixle2 = myBitmap3.GetPixel(400, 250);
if (pixle1 == Color.FromArgb(24, 53, 73) || pixle2 == Color.FromArgb(24, 53,73))
{
myBitmap3.MakeTransparent(Color.FromArgb(24, 53, 73));
gfx.DrawImage(myBitmap3, 1, 1);
GC.Collect();
}
else
{
GC.Collect();
}
}
روش Dispose کردنِ شیِ خروجیِ متدِ زیر که در تایمرهای قبلی ایجاد شده بودن :
را در پست قبلی (پست 18) ، گفتم .
علاوه بر این ، چندین بار دارم میگم که اشیایی که متد Dispose دارن را بعد از استفاده ، Dispose کنید . شیِ myBitmap3 تون هم از این نوع هست و Dispose نکردید .
ضمنا ، نیازی به دو بار اجرای متد GC.Collect نیست . نهایتا میتونید ، یکبار ، اون هم در خط آخر بنویسید . دیگه if و else گذاشتن برای این متد ، معنا نداره .
ضمن اینکه بهتره که این متد را زمانی اجرا کنید که فرضا مقدار اشغالی حافظه ، از یه حدی بیشتر بشه . هر چند مشکلی نداره اما قضیه ی سربار را که گفتم .
نقل قول:
فقط یه سوال البته میدونم زیاد سوال پرسیدم ببخشد شما رو هم اذیت کردم این gc.collect() چطور فریم هایی که توی فرم چاپ شدن رو پاک نمیکنه یعنی برنامه من هیچ ایرادی توش نیفتاد ولی حافظه خالی شد! ظاهرا اشغال حافظه مال همین عکس های چاپ شده توی فرم و توی پیکچرباکس هستن یا من اشتباه میکنم؟
چون گربک کالکتور ، فقط حافظه های managed ای را پاک میکنه که اشاره گری بهش وجود نداشته باشه .
وقتی مینویسید :
کد:
pictureBox1.Image = nextFrame.ToBitmap();
یعنی شیِ Bitmap ای که از خروجیِ متدِ nextFrame.ToBitmap ایجاد میشه ، اشاره گر داره .
اشاره گرش هم پروپرتیِ pictureBox1.Image هست .
بنابراین ، گربگ کالکتور ، حافظه ی managed ئه مربوط به این شی را پاک نمیکنه .
پاسخ: کشیدن یک عکس ردر بکگراند فرم در vb.net
جا داره از آقا سجاد تشکر کنم به خاطر این همه راهنمایی ممنونم