گفتگو هایی در باب سی شارپ

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
البته منظور من ادغام فایل اجرایی ویروس بود (بالاخره ویروس باید اولین بار از جایی اجرا بشه دیگه)
بعد اینکه در مقاله ی زیر :

چرا نمی‌توان به Task Manager ویندوز اعتماد کرد؟

یه تیکه گفته :


"
در شکل بالا Stalled به معنی متوقف شدن پردازنده و پیشروی نکردن اجرای دستورالعمل است که علت اصلی آن منتظر ماندن پردازنده برای انجام عملیات خواندن-نوشتن حافظه اصلی (RAM) است. در شکل بالا نسبت زمان فعالیت پردازنده (Busy) به زمان متوقف شدن پردازنده (Stalled) بسیار به عملکرد در دنیای واقعی نزدیک است. در حقیقت پردازنده سیستم شما وقت بسیار زیادی متوقف می‌شود اما شما از آن بی اطلاع هستید
معیاری که شدت استفاده از پردازنده خوانده می‌شود، در حقیقت زمان بلا استفاده نبودن پردازنده است، به عبارتی دیگر مدت زمانی که پردازنده مشغول اجرای Thread بلا استفادگی سیستم عامل نیست. هسته سیستم عامل شما (هرچه که باشد) به طور مکرر وضعیت آن را پایش می‌کند. اگر یک Thread غیر بلا استفادگی اجرا شود، 100 میلی ثانیه بعد، هسته سیستم استدلال می‌کند پردازنده به طور کامل استفاده شده است.
و ...
"

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

the_king

مدیرکل انجمن
ممنون استاد علی
البته منظور من ادغام فایل اجرایی ویروس بود (بالاخره ویروس باید اولین بار از جایی اجرا بشه دیگه)
بعد اینکه در مقاله ی زیر :

چرا نمی‌توان به Task Manager ویندوز اعتماد کرد؟

یه تیکه گفته :


"
در شکل بالا Stalled به معنی متوقف شدن پردازنده و پیشروی نکردن اجرای دستورالعمل است که علت اصلی آن منتظر ماندن پردازنده برای انجام عملیات خواندن-نوشتن حافظه اصلی (RAM) است. در شکل بالا نسبت زمان فعالیت پردازنده (Busy) به زمان متوقف شدن پردازنده (Stalled) بسیار به عملکرد در دنیای واقعی نزدیک است. در حقیقت پردازنده سیستم شما وقت بسیار زیادی متوقف می‌شود اما شما از آن بی اطلاع هستید
معیاری که شدت استفاده از پردازنده خوانده می‌شود، در حقیقت زمان بلا استفاده نبودن پردازنده است، به عبارتی دیگر مدت زمانی که پردازنده مشغول اجرای Thread بلا استفادگی سیستم عامل نیست. هسته سیستم عامل شما (هرچه که باشد) به طور مکرر وضعیت آن را پایش می‌کند. اگر یک Thread غیر بلا استفادگی اجرا شود، 100 میلی ثانیه بعد، هسته سیستم استدلال می‌کند پردازنده به طور کامل استفاده شده است.
و ...
"
این مطالبی که دارید مطرح می کنید مربوط به این #C میشه؟ اگه مطالب قبلی که گفته بودم رو مجددا مرور کنید میبینید که مقاله به همون مطلبی اشاره میکنه که من بارها گفتم :
این 25 درصد که میگید معیار دقیقی از توان مصرفی پروسه شما در هسته نیست، یک معیار کلی، تخمینی و ظاهریه. صحبت وضعیت یک کسری از ثانیه است، نه کل زمان. همونطور که شما یکسره روبرو تون رو نمی بینید و پلک می زنید، سیستم عامل هم مدام منبعش رو از پروسه شما پس می گیره و دوبار تخصیص میده.
نه، الزاما یک نخ نیست، ممکنه هر چی نخ در اون هسته بوده در یک لحظه به اون پروسه اختصاص داده بشه. بستگی به این داره که برنامه تون چند نخی باشه.
در مورد Task Manager میشه همچین نظری داشت ولی کلا آمار دقیقی نمیده، اگه پردازنده 100 درصد در اختیار برنامه شما است اون Task Manager چطور داره روون کار می کنه؟
و فرض کنیم برنامه شما 16 نخ در حال اجرا داره و میزان اشغال CPU رو به 100% رسوندید ولی همون زمان دارید با ماوس و Task Manager بدون مشکل کار می کنید. این سوئیچ کردن مداوم بین نخ ها همزمانی نیست، حتی قبلتر از اینکه پردازنده های چند هسته ای تولید بشوند هم وجود داشته. برنامه شما هسته های دیگه رو هم درگیر می کنه ولی نه اینکه همزمان چهار تا هسته رو برنامه شما قبضه کنه. سیستم که این همه سرویس و پروسه حیاتی خودش رو معلق نگه نمیداره.
این جمله درست نیست . اینطور نیست؟
همونطور که قبلا گفتید ، پردازنده هر موقع تشخیص داد (مثلا زمان توقف یک نخ یا زمانی که باید منتظر خوندن اطلاعات از رم باشه و یا کلا هر وقت دیگه ای که خودش تشخیص بده که کلا این تشخیص دست خودشه) ، اجرای اون نخ را متوقف میکنه و سراغ نخ دیگه ای میره و بعد از رسیدن اطلات رم ، ادامه ی اجرای نخ قبلی را انجام میده . درسته؟ یعنی کلا منتظر موندن برای پردازنده معنا نداره (چون اون نخ را که منتظرش میذاره را متوقف میکنه و سراغ نخ دیگه میره) . درسته؟

کدوم نخ دیگه؟ اگه همیشه یک نخ و کاری برای انجام وجود داشت که هیچوقت معیار اشغال بودن CPU از 100 درصد پایین نمیومد. CPU مثل موتور ماشین جعبه دنده نداره که موقع بیکاری دنده ها از درگیری دربیان و هرز بچرخه. وقتی کاری برای انجام نداشته باشه منتظر میمونه، اگر منتظر نمونه که بیکار نمیشه :
اما در حالت کلی اصلا حداکثر قدرت پردازنده بدست نمیاد که، یک آمار کلی و حدودی از میزان کارایی پردازنده سیستم تون بگیرید، میبینید که بیشتر وقتش بیکار ئه. این یک معضل جدید نیست، از همون سیستم عامل های ابتدایی همین مساله بوده که پردازنده بیشتر بیکار ئه تا مشغول. معنی اش چیه؟ معنی اش اینه که اگه بشینید کد همه برنامه های روی ویندوز تون رو بازنویسی و بهینه کنید تا بهتر از پردازنده استفاده کنند، نتیجه اش بیکار شدن بیشتر پردازنده است، چون کارشون زودتر تموم میشه. و این هم چیز بدی نیست که بخواهید جلوشو بگیرید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
این مطالبی که دارید مطرح می کنید مربوط به این #C میشه؟ اگه مطالب قبلی که گفته بودم رو مجددا مرور کنید میبینید که مقاله به همون مطلبی اشاره میکنه که من بارها گفتم :




کدوم نخ دیگه؟ اگه همیشه یک نخ و کاری برای انجام وجود داشت که هیچوقت معیار اشغال بودن CPU از 100 درصد پایین نمیومد. CPU مثل موتور ماشین جعبه دنده نداره که موقع بیکاری دنده ها از درگیری دربیان و هرز بچرخه. وقتی کاری برای انجام نداشته باشه منتظر میمونه، اگر منتظر نمونه که بیکار نمیشه :

ممنون استاد علی
خوب نخ ها به سی شارپ مربوط میشه و در این باره قبلا اینجا صحبت کردیم دیگه
منظور من و هم اون مقاله را خوب متوجه نشدین
اول اینکه میدونم اینایی که قبلا گفته بودید . منظور شما اینه که مثلا وقتی task manager نشون میده 25 درصد از پردازنده در حال استفاده هست ، اولا این 25 درصد ممکنه دقیق نباشه و دوما داده های task manager حداکثر 0.2 ثانیه آپدیت میشن در صورتی که سرعت پردازنده بسیار بالاتر هست و ممکنه توی این بازه ی زمانی ، ده ها نخ را متوقف کرده باشه و ده ها نخ دیگه را اجرا کرده باشه و ...
بعد اینکه منظور مقاله چیز دیگه هست . میگه اگه دیدید مثلا در task manager زده 90 درصد از پردازنده در حال استفاده هست ، این طور نیست . در این زمان (زمانی که 90 درصد رو در task manager در حال استفاده نشون میده) ، در واقع خیلی کمتر از اون در حال استفاده هست (مثلا 20 درصد) و بقیه ، منتظر خوندن اطلاعات از رم هست .
یعنی تقریبا 60 درصد را در task manager بیخودی نشون میده که در حال استفاده هست (البته میدونم زمان جابجایی نخ ها ، تاخیر داره)
 

the_king

مدیرکل انجمن
ممنون استاد علی
خوب نخ ها به سی شارپ مربوط میشه و در این باره قبلا اینجا صحبت کردیم دیگه
منظور من و هم اون مقاله را خوب متوجه نشدین
اول اینکه میدونم اینایی که قبلا گفته بودید . منظور شما اینه که مثلا وقتی task manager نشون میده 25 درصد از پردازنده در حال استفاده هست ، اولا این 25 درصد ممکنه دقیق نباشه و دوما داده های task manager حداکثر 0.2 ثانیه آپدیت میشن در صورتی که سرعت پردازنده بسیار بالاتر هست و ممکنه توی این بازه ی زمانی ، ده ها نخ را متوقف کرده باشه و ده ها نخ دیگه را اجرا کرده باشه و ...
بعد اینکه منظور مقاله چیز دیگه هست . میگه اگه دیدید مثلا در task manager زده 90 درصد از پردازنده در حال استفاده هست ، این طور نیست . در این زمان (زمانی که 90 درصد رو در task manager در حال استفاده نشون میده) ، در واقع خیلی کمتر از اون در حال استفاده هست (مثلا 20 درصد) و بقیه ، منتظر خوندن اطلاعات از رم هست .
یعنی تقریبا 60 درصد را در task manager بیخودی نشون میده که در حال استفاده هست (البته میدونم زمان جابجایی نخ ها ، تاخیر داره)
مباحثی که می کنید مربوط به #C نیست، مربوط به معماری پردازنده است، اینکه Task Manager چی رو نشون میده یا نمیده هم باز ربطی به #C نداره.
ولی در کل تفسیری که شما از مطلب می کنید تفسیر درستی نیست. پردازنده بیخودی منتظر نیست. یک کدی اجرا می کنه که عملیاتی روی داده ای باید انجام بده، داده درخواست میشه، صبر می کنه که داده بیاد و بعد عملیات رو روی داده انجام میده. کل زمان این فرمان برای اجرا شدن اون دستور لازمه، نمیشه که بگیم فقط بخش اولش یا فقط بخش آخرش یا همه بجز بخش وسطیش جزو فعالیت پردازنده است و بقیه بیخودیه. پردازنده داره یک کد رو اجرا میکنه که منتظره، کل زمان از ابتدا تا انتها مشغوله. انتظار جزئی از روالشه. مثل لامپ پر مصرف که بخش زیادی از انرژی اش با تولید حرارت بجای نور هدر میره، پردازنده هم بخشی از انرژی اش در زمان انتظار تلف میشه. لامپ در حین کار همزمان هم داره نور تولید می کنه و هم حرارت. اینها در کنار همه، تفکیک شده نیست. نمیگیم لامپ 60 درصد زمان روشنه و 40 درصد زمان روشن نیست و خاموشه و بجاش حرارت تولید می کنه، پس وقتی میگه لامپ 10 ساعت روشن بوده اشتباه میگه، 6 ساعت روشن بوده و 4 ساعت بیخودیه.
وقتی هم پردازنده داره کد های زبان ماشین رو اجرا می کنه وقفه ها برای ارتباط با سایر اجزاء در مسبر های ارتباطی بوجود میاد، این انتظار ها جزئی از کارکرد طبیعی پردازنده است. مثل همون تولید همزمان نور و حرارت.
پردازنده بیکار که منتظر داده ای نیست، وقتی کاری نداشته که انجام بده داده به چه دردش می خوره؟ پردازنده بیکار کدی اجرا نکرده که داده ای درخواست کنه که حالا بخواد از حافظه RAM خونده بشه. در معماری پردازنده های مدرن هم این امکان هست که وقتی پردازنده منتظر داده از گذرگاه RAM ئه و نمیتونه کد دیگری رو که مرتبط با حافظه است اجرا کنه، بتونه کد دیگری که به حافظه RAM مربوط نیست رو اجرا کنه. که باز هم بحث معماری ئه، و ربطی به #C نداره. اینکه پردازنده کارایی اش بخاطر کندی حافظه پایین میاد به این معنی نیست که انتظار پردازنده جزو روال کارکردنش نیست. در این مورد Task Manager رفتار اشتباهی نداره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
ممنون استاد علی
توی form1 وقتی هستیم ، به عضو DoubleBuffered دسترسی داریم (بخاطر اینکه درون form1 هستیم که به اعضای protected پدرانش دسترسی داره)
ولی میشه کاری کرد که همین عضو DoubleBuffered ، برای کنترل هایی که به form1 اضافه میکنیم (مثل کنترل panel1) ، در دسترس باشه؟ اگه آره ، چجوری؟
 

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
توی form1 وقتی هستیم ، به عضو DoubleBuffered دسترسی داریم (بخاطر اینکه درون form1 هستیم که به اعضای protected پدرانش دسترسی داره)
ولی میشه کاری کرد که همین عضو DoubleBuffered ، برای کنترل هایی که به form1 اضافه میکنیم (مثل کنترل panel1) ، در دسترس باشه؟ اگه آره ، چجوری؟
قاعدتا باید روش اش رو بدونید. یا باید با Reflection و GetProperty پروپرتی اش رو بصورت PropertyInfo بدست بیاورید و SetValue و GetValue کنید که در واقع سطح دسترسی های تعیین شده مثل protected رو دور می زنه. یا باید از طریق متد ها یا پروپرتی های واسطه ای که میسازید دسترسی غیر مستقیم رو فراهم کنید.
سایر کلاس ها به اون یک مورد protected که در هر حال نمیتوانند دسترسی مستقیم داشته باشند، چون کد کلاس Control رو که نمی توانید تغییر بدید و protected رو public کنید. اما چون به کد کلاس Form1 دسترسی دارید می توانید به عنوان مثال یک پروپرتی public دیگه ای مثل MyDblBuffered بسازید که روی اون DoubleBuffered کار کنه یا اصلا یک پروپرتی جدید با همون نام DoubleBuffered بسازید بصورت public new bool DoubleBuffered که روی اون base.DoubleBuffered کار کنه. کنترل هایی مثل panel1 دیگه DoubleBuffered رو با متد new شما میشناسند نه اونی که Control داشته که protected بوده.
و تا حد امکان از Reflection وtypeof(Form1).GetProperty و موارد اینچنینی اجتناب کنید، در کل هم از نظر کارایی کند ئه و هم نظم اصول عادی کدنویسی که بر پایه سطح دسترسی ها بود بهم میزنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله ممنون استاد علی . حواسم به new کردن نبود
میگم توی سی شارپ ، مثلا استراکچری که درست میکنیم ، سازگار با کدهای unmanaged هست یا باید استراکچر سی شارپ رو هم توسط کلاسی مثل Marshal ، توی استراکچر Unmanaged بریزیم؟ (قاعدتا نباید سازگار باشه دیگه؟)
بعد اینکه بجز استفاده از کدهای unsafe ، میشه اشاره گر به استراکچرها را در سی شارپ گرفت؟ (منظورم آدرس خونه ی استراکچر هست)
بعد هم اینکه توی کدهای managed که گفتین هر لحظه ممکنه آدرس حافظه اش تغییر کنه ؛ توی کدهای Unmanaged این طور نیست و آدرس شون ثابت اند؟ اگه آره ، چرا توی کدهای managed ، آدرس حافظه ممکنه هر لحظه تغییر کنه ولی در Unmanaged نه؟ یعنی دلیل اینکه کدهای Managed را این طور طراحی کردن ، چیه؟ چرا مثل Unmanaged ، آدرس را ثابت نذاشتن؟
ممنون
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
و کلا اینکه میشه استراکچری که در سی شارپ داریم را از درون خود سی شارپ ، توی حافظه ی جدید Unmanaged ای بریزیم (حافظه ی Unmanaged ای که قبلا ساخته و Allocate شده باشه رو منظورم نیست بلکه منظورم اینه که توی خود سی شارپ این Allocate برای حافظه ی Unmanaged صورت بگیره) و بعد هم اشاره گرِ (Intptr) این استراکچر در حافظه ی Unmanaged را بدست بیاریم؟
اگه آره ، با کدوم کلاس یا متد؟
توی کلاس Marshal ، چیزی که به درد این کار بخوره را پیدا نکردم

--------------------------------------------------------------------------------

ویرایش :
پیدا کردم جواب رو
با استفاده از متد Marshal.AllocHGlobal حافظه ی Unmanaged اختصاص داده میشه
تابع Marshal.SizeOf هم اندازه را برمیگردونه

اما با استفاده از تابع Marshal.SizeOf ، یه استراکچری را که دو فیلد int داشت و دو پروپرتی ای (یکی int و یکی هم string که طبعا string کلاس هه و اشاره گر و چون برنامه ام 32 بیتی هست ، باید اشاره گرِ string ، چهار بایت باشه) که از پیاده سازی کردن یه اینترفیس داشت ، این تابع Marshal.SizeOf ، مقدار 8 (بایت) را برگردوند . یعنی اون اعضایی که پیاده سازی شدن از اینترفیس را حساب نکرد؟ وگرنه باید 16 (بایت) را برمیگردوند
 
آخرین ویرایش:

the_king

مدیرکل انجمن
بله ممنون استاد علی . حواسم به new کردن نبود
میگم توی سی شارپ ، مثلا استراکچری که درست میکنیم ، سازگار با کدهای unmanaged هست یا باید استراکچر سی شارپ رو هم توسط کلاسی مثل Marshal ، توی استراکچر Unmanaged بریزیم؟ (قاعدتا نباید سازگار باشه دیگه؟)

تا سازگاری رو چی تعریف کنید، struct همیشه یک معادل داره که یک حافظه به طول کل struct ئه، می توانید محتویاتش رو در حافظه Unmanaged کپی کنید و برعکس.

بعد اینکه بجز استفاده از کدهای unsafe ، میشه اشاره گر به استراکچرها را در سی شارپ گرفت؟ (منظورم آدرس خونه ی استراکچر هست)
سوالتون مبهمه، تا اونجایی که به ساختار حافظه مربوطه، آدرس اولین فیلد از ساختار، آدرس شروع اون ساختار هم هست.
بعد هم اینکه توی کدهای managed که گفتین هر لحظه ممکنه آدرس حافظه اش تغییر کنه ؛ توی کدهای Unmanaged این طور نیست و آدرس شون ثابت اند؟ اگه آره ، چرا توی کدهای managed ، آدرس حافظه ممکنه هر لحظه تغییر کنه ولی در Unmanaged نه؟ یعنی دلیل اینکه کدهای Managed را این طور طراحی کردن ، چیه؟ چرا مثل Unmanaged ، آدرس را ثابت نذاشتن؟
ممنون
حافظه Unmanaged هم صرفا یک شرایط یکسان نداره، فرض کنید ایجاد کننده اون حافظه Unmanaged پروسه ای در برنامه دیگری باشه، مثلا یک بازی در حال اجرا. هیچ تضمینی وجود نداره که این حافظه لحظه بعد معتبر باشه، آزاد نشه، جابجا نشه و ...

اما با استفاده از تابع Marshal.SizeOf ، یه استراکچری را که دو فیلد int داشت و دو پروپرتی ای (یکی int و یکی هم string که طبعا string کلاس هه و اشاره گر و چون برنامه ام 32 بیتی هست ، باید اشاره گرِ string ، چهار بایت باشه) که از پیاده سازی کردن یه اینترفیس داشت ، این تابع Marshal.SizeOf ، مقدار 8 (بایت) را برگردوند . یعنی اون اعضایی که پیاده سازی شدن از اینترفیس را حساب نکرد؟ وگرنه باید 16 (بایت) را برمیگردوند
بله، در struct موقعیت هر فیلد صریحا در اون حافظه struct مشخص میشه، پروپرتی و متد کلا در این قضیه ذخیل نیستند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سوالتون مبهمه، تا اونجایی که به ساختار حافظه مربوطه، آدرس اولین فیلد از ساختار، آدرس شروع اون ساختار هم هست.

ممنون
منظورم بدست آوردن اشاره گر (Intptr) مربوط به ون استراکچر یا همون Intptr از اولین فیلد استراکچر هست
حالا چون حافظه هر لحظه ممکنه جابجا بشه ، بدست آوردن اشاره گر هم فایده ای نباید داشته باشه


حافظه Unmanaged هم صرفا یک شرایط یکسان نداره، فرض کنید ایجاد کننده اون حافظه Unmanaged پروسه ای در برنامه دیگری باشه، مثلا یک بازی در حال اجرا. هیچ تضمینی وجود نداره که این حافظه لحظه بعد معتبر باشه، آزاد نشه، جابجا نشه و ...

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

the_king

مدیرکل انجمن
ممنون
منظورم بدست آوردن اشاره گر (Intptr) مربوط به ون استراکچر یا همون Intptr از اولین فیلد استراکچر هست
حالا چون حافظه هر لحظه ممکنه جابجا بشه ، بدست آوردن اشاره گر هم فایده ای نباید داشته باشه
ماهیت قضیه رو باید در نظر بگیرید. شما وقتی با محیط داخل NET. سر و کار دارید جابجا شدن حافظه یک شیء از دید شما پنهانه، هیچوقت مشکلی با جابجا شدن ها برای کدتون ایجاد نمیشه چون مدیریت حافظه با شما نیست. هیچوقت با این مساله مواجه نمیشید که NET. بهتون بگه ببخشید این حافظه جاش عوض شد پس الان دیگه نمیتونم شیء تون رو پیدا کنم. جابجایی ها کاملا از دید کدتون پنهانه. اما شما دارید در مورد ارتباط بین حافظه Managed و Unmanaged صحبت می کنید، نه حافظه داخل Managed . اون IntPtr ای که مستقیما از شیء میگیرید در دنیای خارج از محیط ماشین مجازی معنایی نداره. و در اینجا اشاره گر به یک حافظه Managed خودش ابدا بدرد Unmanaged نمیخوره، دو تا دنیا متفاوت دارند. قبلا هم این مساله رو بارها گفتم. ماشین مجازی حافظه اش کاملا مستقل ئه. شما به GCHandle احتیاج دارید که میتونه با AddrOfPinnedObject یک آدرس ثابت Unmanaged از اون شیء رو بهتون بده و البته نهایتا باید Free اش کنید چون با ساختن GCHandle شی به اصطلاح Pin شده و با پونز جاش روی حافظه ثابت شده و GC نمیتونه جابجاش کنه.
آدرس حافظه ی Unmanaged هم ممکنه جابجا بشه؟!!
پس چطور توی یه نرم افزار و پروسه ای (مثلا اتوپلی) یه اشاره گرش را میدیم به سی شارپ (و با Marshal اون حافظه ی Unmanaged را توی حافظه ی Managed کپی میکنیم) و کلا ازش استفاده میکنیم؟
اگه این هر لحظه احتمال جابجایی داشته باشه که باید ارور بده
ممکنه جابجا بشه با قطعا جابجا میشه دو تا مورد کاملا جداست. ممکنه جابجا بشه اما خود بخود که جابجا نمیشه. چطور که اگر GC ای در کار نبود خود بخود که حافظه اشیاء NET. جابجا نمیشد.
وقتی برنامه کدی اجرا نکرده که اون حافظه رو از اعتبار بندازه خوب عملی صورت نگرفته که ارور بده. ویژوال بیسیک 6 مگه خارج از محیط NET. نیست؟ اونم حافظه اشاره گر هایش ممکنه تغییر کنه و منجر به کرش کدی بشه که گمان میکرده آدرس حافظه همیشه بلا تغییر میمونه.
بعد هم اینکه قبلا گفته بودین آدرسی که توسط هر پروسه داده میشه ، آدرس فیزیکی نیست و آدرس تعریف شده ای هست که صرفا به نسبت همون پروسه تعریف میشه . پس چطور آدرس اشاره گر Unmanaged ای که در اتوپلی تعریف کردیم را به سی شارپ میدیم ، سی شارپ ارور نمیده؟ چون سی شارپ نباید به پروسه ی دیگه (که آدرس حافظه نسبت به اون پروسه هست) ، براش قابل درک باشه بجز اینکه آدرس فیزیکی باشه
اشتباه تون همونجا است که تصور می کنید فیزیکیه. آدرس فیزیکی آدرس حافظه RAM ئه، هیچ برنامه ای در سطح خارج هسته به این حافظه دسترسی نداره، برنامه شما در سیستم عامل در سطح کاربری اجرا میشه و صرفا به حافظه مجازی ای دسترسی داره که سیستم عامل در اختیارش قرار میده، پس عبارت حافظه فیزیکی رو کلا از تو کلام تون جمع کنید بذارید کنار، شما برای هسته سیستم عامل کد نمی نویسید که چیزی بنام حافظه فیزیکی در کدتون وجود داشته باشه. شما اصلا آدرس حافظه فیزیکی در کد نویسی Managed و Unmanaged ندارید، حتی یک عدد آدرس حافظه فیزیکی ندارید. در ضمن شما آدرسی رو که پروسه داخل خودش استفاده می کنه رو به #C نمی دهید. شما کد زبان ماشین داخل پروسه اتوپلی که در حال اجراست رو نمی بینید که داره با آدرسی که 0 اش شروع حافظه خودشه کار می کنه. اون آدرس حافظه ای هم که به #C می فرستید یک آدرس مجازیه که تفسیرش با مدیر حافظه سیستم عامل ئه، ابدا فیزیکی نیست، قبلا هم گفتم که چطور جابجایی و Defrag شدن کلاستر های فایل روی هارد دیسک دائما اتفاق می افته ولی اختلالی در اجرای برنامه ها ایجاد نمی کنه، جابجایی پیج های حافظه هم دائم توسط بخش مدیریت حافظه سیستم عامل رخ میده ولی پروسه ها بدون اختلال به کارشون ادامه میدن و متوجه جابجا شدن تکه ها هم نیستن. آدرسی که باهاش کار میکنن هم چون نسبت به خودشون میسنجن تغییر نمی کنه. خود سیستم عامل میدونه چطور اون آدرس مجازی رو به آدرس فیزیکی تبدیل کنه، شما و در ارتباط بین پروسه ها صرفا با اون آدرس مجازی سر و کار دارید که خود سیستم عامل بهتون میده، شما از کد زبان ماشین آدرس استخراج نمی کنید که نسبت به شروع پروسه باشه. یک چیزی مثل اون AddrOfPinnedObject و مثل AllocHGlobal ئه. همونطور که شما سکتور های دیسک رو نمی بینید، آدرس های داخل پروسه رو هم نمی بینید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
پس سیستم عامل هه که کنترل میکنه

----------------------------------------

موقع نصب ویژال استودیو یه گزینه ای بنام windows 8.1 sdk یا windows 10 sdk میاد ، چیه؟
چه کتابخونه ای هست و مثلا باهاش میشه چی کارها کرد و چه نوع پروژه ای نوشت؟
 

the_king

مدیرکل انجمن
موقع نصب ویژال استودیو یه گزینه ای بنام windows 8.1 sdk یا windows 10 sdk میاد ، چیه؟
چه کتابخونه ای هست و مثلا باهاش میشه چی کارها کرد و چه نوع پروژه ای نوشت؟
هر چیزی که برای توسعه نرم افزار بر پایه یک پلتفرم خاص لازم باشه داخل SDK اش قرار میگیره، فقط کتابخانه نیست، ابزار ها و مستندات و ... هم هستند.
مثل NET SDK. و Android SDK و Windows SDK و Java EE SDK و ...
بعضی IDE ها بهش وابستگی کامل دارند و بدون وجود SDK فایل اجرایی نمی سازند، ولی بعضی هاشون وابستگی ندارند، مثلا ویژوال بیسیک کلاسیک نیازی به وجود Windows SDK نداشت،
ولی فرضا ویژوال استدیو و اندروید استدیو به SDK ویندوز و اندروید نیاز اساسی دارند. چون با زبان هایی مثل ++C سر و کار ندارید خیلی به چشم نمیاد، ولی بهر حال در ویژوال استدیو برای ایجاد فایل اجرایی
پروژه #C تون هم از SDK ویندوز استفاده میشه. ولی بیشترین استفاده از Windows SDK رو در زبان های ++C/C میشه داشت چون به همون زبانها است و قابل استفاده برای کامپایلر شون.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
هر چیزی که برای توسعه نرم افزار بر پایه یک پلتفرم خاص لازم باشه داخل SDK اش قرار میگیره، فقط کتابخانه نیست، ابزار ها و مستندات و ... هم هستند.
مثل NET SDK. و Android SDK و Windows SDK و Java EE SDK و ...
بعضی IDE ها بهش وابستگی کامل دارند و بدون وجود SDK فایل اجرایی نمی سازند، ولی بعضی هاشون وابستگی ندارند، مثلا ویژوال بیسیک کلاسیک نیازی به وجود Windows SDK نداشت،
ولی فرضا ویژوال استدیو و اندروید استدیو به SDK ویندوز و اندروید نیاز اساسی دارند. چون با زبان هایی مثل ++C سر و کار ندارید خیلی به چشم نمیاد، ولی بهر حال در ویژوال استدیو برای ایجاد فایل اجرایی
پروژه #C تون هم از SDK ویندوز استفاده میشه. ولی بیشترین استفاده از Windows SDK رو در زبان های ++C/C میشه داشت چون به همون زبانها است و قابل استفاده برای کامپایلر شون.

ممنون
ولی اگه یه مثال میزدین که مثلا چه نوع کتابخونه ای و برای چه کارهایی توش هستن ، برام درکش ملموس تر میشد .
برای ما لازمه که نصبش کنیم؟ به کار ما میاد؟
 

the_king

مدیرکل انجمن
ممنون
ولی اگه یه مثال میزدین که مثلا چه نوع کتابخونه ای و برای چه کارهایی توش هستن ، برام درکش ملموس تر میشد .

این کتابخانه که شما منظورتونه نیست، به اون مفهوم dll جدیدی نیست که یک چیزی باشه که کنار برنامه تون قرار بدید و به قابلیت های برنامه تون اضافه کنه. کسی که میاد در زبان ++C/C از API ویندوز استفاده می کنه، از یکی از کتابخانه های ویندوز مثل user32.dll یک متد API رو استفاده کنه، مجبور نیست مثل کدی که در #C می نویسید اول متد رو تعریف کنه، یا نمیاد متغیر ثابت WM_CLOSE رو از نو تعریف کنه، چون تو خود اون SDK از قبل کامل همه شون تعریف شده، میاد فقط با یک سطر کد کل تعاریف رو یکجا include اش می کنه در پروژه اش و به راحتی استفاده می کنه. نه اینکه Wrapper باشه، خود متد ها رو مستقیم از dll های ویندوز فراخوانی کنه. پس به اون معنی کتابخانه ای در کار هست، ولی از قبل در سیستم عامل بود، چیز جدیدی نیست. همونا که از ابتدا در ویندوز هست، فقط برای استفاده در برنامه نویسی به تعاریف احتیاج داره که داخل SDK ئه. این SDK برای توسعه برنامه برای سیستم عامل ویندوز ئه که تمرکزش هم روی ++C/C ئه، نه اینکه چیزی اضافه کنه که قبلا نبوده.
هر چیزی که مربوط به استفاده نرم افزار های سطح کاربر ویندوز ئه، یعنی تعاریف API و struct ها و مقادیر ثابت تعریف شده و همه اون اینترفیس ها و متد هایی که مربوط به API ئه و ... داخل اون SDK ئه.
Overview of the Windows SDK

برای ما لازمه که نصبش کنیم؟ به کار ما میاد؟
نه. به احتمال زیاد بکارتون نمیاد. نمیشه گفت که الان که مستقیم نصبش نکردید اصلا Windows SDK نصب شده روی سیستم ندارید، همراه ویژوال استدیو چه بخواهید و چه نخواهید بخش کوچکی از Windows SDK که ابزار های مورد نیازشه نصب شده. کل SDK نیست ولی در حدی که مثلا در #C لازمش داشته نصب شده. اما اون چیزی که میتوانید تیک بزنید و نصب کنید، نسخه کامل تری است که در سایت مایکروسافت هم یکجا و مستقل قابل دانلوده و بیشتر قابل استفاده در زبان های ++C / C ئه که میخواهند فرضا برای ویندوز نسخه فلان بر اساس قابلیت های خاص اون نسخه یک برنامه بنویسند و توابعی رو بکار ببرند که در نسخه های قبلی ویندوز نبوده. برای #C مستقیم استفاده خاصی نداره، چون اگه بخواهید از API استفاده کنید یا خودتون تعاریف رو بازنویسی می کنید و یا از یک Wrapper آماده استفاده می کنید. مگر اینکه حالتی خیلی خاصی باشه، از یک Extension ای یا کد source کتابخانه ای چیزی استفاده کنید که لازم باشه ابتدا کدی رو کامپایل کنه که به زبان #C نیست، مثل یک کد ++Visual C یا حالتی شبیه به این. مستقیم هم می توانید Windows SDK نسخه های مختلف رو از سایت مایکروسافت بصورت iso دانلود کنید، ولی در کل در #C نهایت استفاده تون ازش اینه که بخواهید در header هاش مقدار عددی یک define رو پیدا کنید، چندان بکارتون نمی یاد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
میگم چرا کد زیر را که مینویسم :


کد:
        public static WindowsMediaPlayer wmp;

       public static void PlaySound(string filePath)
        {
            WMPlayer.wmp = new WindowsMediaPlayer();
            WMPlayer.wmp.URL = filePath;
            WMPlayer.wmp.controls.play();
        }

در شی WMPlayer.wmp دیگه رویداد PlayStateChange را نمیشه مقداردهی کرد؟! یعنی new که میکنم ، نام WMPLib._WMPOCXEvents_PlayStateChangeEventHandler توی لیستم نمیاد اما مستقیم اگه نام تابع مورد نظر برای این رویداد را بدون new کردن دلیگیت اش بدم ، مشکلی نمیگیره و کار میکنه
چرا؟!
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یه چیز دیگه اینکه ورودی تابع زیر را هر چی که میدم (مثلا مقدار 10) ، کار نمیکنه به اون اندازه جلو نمیره آهنگ :

کد:
        public static void SetPos(double forward)
        {
            WMPlayer.wmp.controls.currentPosition = WMPlayer.wmp.controls.currentPosition + forward;
        }

چرا؟!
 

the_king

مدیرکل انجمن
ممنون استاد علی
میگم چرا کد زیر را که مینویسم :


کد:
        public static WindowsMediaPlayer wmp;

       public static void PlaySound(string filePath)
        {
            WMPlayer.wmp = new WindowsMediaPlayer();
            WMPlayer.wmp.URL = filePath;
            WMPlayer.wmp.controls.play();
        }

در شی WMPlayer.wmp دیگه رویداد PlayStateChange را نمیشه مقداردهی کرد؟! یعنی new که میکنم ، نام WMPLib._WMPOCXEvents_PlayStateChangeEventHandler توی لیستم نمیاد اما مستقیم اگه نام تابع مورد نظر برای این رویداد را بدون new کردن دلیگیت اش بدم ، مشکلی نمیگیره و کار میکنه
چرا؟!
اینکه چرا delegate اش رو نمی بینید رو نمی دونم ولی هیچ مشکلی نداره، در ضمن مقدار دهی منظورتون چیه؟ اگه منظورتون اضافه کردن متد به رخداد ئه، لابد میدونید که باید =+ و =- رو بکار ببرید، نه = رو.
اون WMPLib._WMPOCXEvents_PlayStateChangeEventHandler یک delegate ساده public است و هیچکسی نمیتونه مانع استفاده اش بشه.
اما new کردن که ربطی به سمت چپ نداره، شما همچین کدی رو بنویسید، لزومی نداره حتما رویداد PlayStateChange باشه که شدن و نشدنش رو بررسی کنید :
کد:
            var ee = new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(Wmp_PlayStateChange);

        private void Wmp_PlayStateChange(int NewState)
        {
        }
اگر هم از ابزار های جانبی مثل Resharper کمک می گیرید فراموش نکنید که همیشه احتمال قاطی کردنش هست که نیاز به Clear Caches کردن از Options داخلش و باز و بسته کردن مجدد Visual Studio داره.
 

the_king

مدیرکل انجمن
یه چیز دیگه اینکه ورودی تابع زیر را هر چی که میدم (مثلا مقدار 10) ، کار نمیکنه به اون اندازه جلو نمیره آهنگ :

کد:
        public static void SetPos(double forward)
        {
            WMPlayer.wmp.controls.currentPosition = WMPlayer.wmp.controls.currentPosition + forward;
        }

چرا؟!
ایراد از این کد نیست، به Codec ها هم بستگی داره ولی کدتون رو بررسی کنید، ببینید SetPos رو کجا و چطور فراخوانی می کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اینکه چرا delegate اش رو نمی بینید رو نمی دونم ولی هیچ مشکلی نداره، در ضمن مقدار دهی منظورتون چیه؟ اگه منظورتون اضافه کردن متد به رخداد ئه، لابد میدونید که باید =+ و =- رو بکار ببرید، نه = رو.
اون WMPLib._WMPOCXEvents_PlayStateChangeEventHandler یک delegate ساده public است و هیچکسی نمیتونه مانع استفاده اش بشه.
اما new کردن که ربطی به سمت چپ نداره، شما همچین کدی رو بنویسید، لزومی نداره حتما رویداد PlayStateChange باشه که شدن و نشدنش رو بررسی کنید :
کد:
            var ee = new WMPLib._WMPOCXEvents_PlayStateChangeEventHandler(Wmp_PlayStateChange);

        private void Wmp_PlayStateChange(int NewState)
        {
        }
اگر هم از ابزار های جانبی مثل Resharper کمک می گیرید فراموش نکنید که همیشه احتمال قاطی کردنش هست که نیاز به Clear Caches کردن از Options داخلش و باز و بسته کردن مجدد Visual Studio داره.

ممنون استاد علی
بله
با =+ این کار رو میکنم . از resharper هم استفاده نمیکنم . ولی توی اینتل لایسنس اون دلیگیت WMPLib._WMPOCXEvents_PlayStateChangeEventHandler را وقتی مینویسم ، نمیاره



ایراد از این کد نیست، به Codec ها هم بستگی داره ولی کدتون رو بررسی کنید، ببینید SetPos رو کجا و چطور فراخوانی می کنید.

کدم واسه اتوپلی هست . اونجا مشکلی نیست .
کلا این کد سی شارپ هست :


کد:
    public class WMPlayer
    {
        public static WindowsMediaPlayer wmp;


        [DllExport("PlaySound", CallingConvention.StdCall)]
        public static void PlaySound(string filePath)
        {
            WMPlayer.wmp = new WindowsMediaPlayer();
            WMPlayer.wmp.URL = filePath;
            WMPlayer.wmp.controls.play();
        }

        [DllExport("SetPos", CallingConvention.StdCall)]
        public static void SetPos(double forward)
        {
            WMPlayer.wmp.controls.currentPosition = WMPlayer.wmp.controls.currentPosition + forward;
        }
    }

حالا کلاس دیگه ای هم درون این فضای نام (کنار این کلاس) هست
و کد اتوپلی هم :


کد:
hDll = Library.Load("AMS_CS.dll", false);
if(hDll == nil) then
return;
end

hDll.SetPos(10);

hDll:Close_();

البته بعد از لود آهنگ یعنی بعد از کد زیر که در دکمه ی دیگه هست ، کد بالا را استفاده میکنم :


کد:
hDll = Library.Load("AMS_CS.dll", false);
if(hDll == nil) then
return;
end

soundFilePath = [[E:\Mp3\Mp3\CD 1\Hamed Zamani\1\Khabari Hast (128).mp3]];
hDll.PlaySound(soundFilePath);

hDll:Close_();
 

جدیدترین ارسال ها

بالا