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

the_king

مدیرکل انجمن
ممنون استاد علی . درباره ی جواب GC ، در حال خوندن هستم
-------------------------
میدونم مجزا هستن
ولی من متد OnClick (که در کلاس Control بصورت Virtual تعریف شده) را که در کلاس فرم ام (FormTest) اورراید میکنم ، وابسته به شی خاصی نیست . یعنی این طور نیست که این متد OnClick را فقط برای رویداد کلیک شی FormTest اورراید کنم
حالا اگه بخوام این متد OnClick را برای رویداد کلیک شی button19 اجرا بشه ، باید کد رو چجوری تغییر بدم؟
کلاسش رو باید Override کنید، شما کلاس Form1 رو تغییر میدید و OnClick ئه Form1 رو override می کنید، نه Form.OnClick ، حالا مشابهش باید در یک کلاس از Button ارث بری کنید و اون button19 رو از اون نوع قرار بدید و بعد OnClick رو در کلاسش Override کنید. وگرنه Button.OnClick که کدش ثابته، نمیشه تغییرش داد.
 

the_king

مدیرکل انجمن
ممنون استاد علی . متوجه شدم
کلا هدف من که آزادسازی حافظه هایی که هیچ اشاره گری نداره را پوشش میده
ولی باید خود متد Collect را جوری طراحی میکردن که نیاز به تابع مکمل ای برای هدف اصلی اش که آزادسازی حافظه های بدون اشاره گره ، نداشته باشه یا حداقل توی ورودی متد Collect ، یه bool میگرفتن که این عملی که متد WaitForPendingFinalizers انجام میده رو توش انجام بدن یا نه (چون خیلی از افراد مبتدی مثل ا که نمیدونیم مکملی هم داره یا نه)
درباره ی Collect دومی ، مورد اضافی نیست . اگه دومی نباشه ، حافظه آزاد نمیشه (اگه همون مثلا کد بالا رو تست کنین بدون Collect دومی)
ماشین مجازی مدام در حال کار ئه، متوقف که نشده. اگه کسی بهتون توصیه کرده باید برای آزاد کردن حافظه اشیاء بلااستفاده در NET. کاری انجام بدید و از GC.Collect استفاده کنید، معلومات زیادی نداشته. استاد که هیچی، کسی که یکبار توضیحات یک متد رو بخونه میفهمه که GC.Collect کاربرد عمومی در برنامه نویسی نداره و استفاده هاش خیلی محدود ئه.
Conditions for a garbage collection
Garbage collection occurs when one of the following conditions is true:
The system has low physical memory. This is detected by either the low memory notification from the OS or low memory indicated by the host.
The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.
The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.
کلا هدف تون کارآمد نیست، یعنی در برنامه نویسی کاربردی نداره. مثالش مثل کارواش میمونه، شما از لحظه ای که ماشین رو از کارواش دربیارید ماشین در حال کثیف شدنه، بعد تمیز شدنش با میکروسکوپ بررسی بشه باز ماشین تمیز از کارواش در نمیاد و روش گرد و خاک و دوده و چربی هست. تمیزی خوبه، پس باید ماشین هر ساعت دوباره بره کارواش؟ نه. نه منطقی ئه و نه مفید. کارواش رفتن هم استهلاک داره، هم هزینه داره و هم زمان بر ئه و هم جلوی استفاده ماشین رو میگیره. GC باید وقتی حافظه اشیاء بلااستفاده رو آزاد کنه که لازم و مفید باشه. این چیزی نیست که شما بتوانید یا لازم باشه تشخیص بدید یا در موردش دخالتی بکنید. GC هر لحظه که پروسه رو بررسی کنه، یکسری شیء بلا استفاده است که حافظه شون آزاد نشده. چون این پروسه در ماشین مجازی در حال کار ئه. مثل بدن انسان. هر لحظه که از حموم دربیایید هم پوشیده از چربی و باکتری و ویروس و ... ئه. بدن مدام هم عرق می کنه و هم چربی ترشح می کنه. اینکه ماشین مجازی هیچ شی بلا استفاده ای در حافظه نداشته باشه نه پایدار ئه، نه مفید ئه و نیازی هست که اینطور باشه. هم سربار داره، هم منابع سیستم رو تلف می کنه و هم فایده ای نداره. شما وقت ارزشمند سیستم رو تلف می کنید برای یکسری بایت هایی که آزاد شدنش هیچ کمکی نمی کنه. اگه فکر می کنید استفاده از GC.Collect مفید ئه اشتباه فکر می کنید. اگه کسی هم بهتون توصیه کرده اونم اشتباه فکر می کنه. ایراد از GC.Collect نیست که پروسه هنوز اشیاء بلاستفاده داره، کار اون ایرادی نداره، در جهت بهتر مدیریت کردن منابع ئه. اشکال از شما است. اینکه شما GC.Collect رو اجرا می کنید کار مفیدی نیست، مضر ئه. حالا وقت پردازنده رو میگیرید به کنار، یه WaitForPendingFinalizers هم به اون اضافه می کنید که پروسه خودتون هم معطل بشه. چه کاریه؟ وسواس ئه. نه کارایی پروسه تون رو بیشتر می کنه و نه سیستم عامل رو. کمکی هم به مدیریت منابع نمی کنه. اینکار تون فقط هدر دادن منابع ئه. تفکر تون نسبت به حافظه آزاد نشده شبیه وسواسی ها است، کیفیت برنامه نویسی بر اساس سهولت و سرعت و کارایی و انتقال پذیری و استفاده مجدد پذیری و ... سنجیده میشه، نه کاهش کارایی GC بخاطر وسواس بی فایده. حالا خودتون اینطوری فکر می کنید به کنار، انتقاد هم می کنید که چرا طوری نساختنش که بیشتر کند بشه و کارایی سیستم رو بهتر بیارید پایین؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کلاسش رو باید Override کنید، شما کلاس Form1 رو تغییر میدید و OnClick ئه Form1 رو override می کنید، نه Form.OnClick ، حالا مشابهش باید در یک کلاس از Button ارث بری کنید و اون button19 رو از اون نوع قرار بدید و بعد OnClick رو در کلاسش Override کنید. وگرنه Button.OnClick که کدش ثابته، نمیشه تغییرش داد.
کلاسش رو باید Override کنید، شما کلاس Form1 رو تغییر میدید و OnClick ئه Form1 رو override می کنید، نه Form.OnClick ، حالا مشابهش باید در یک کلاس از Button ارث بری کنید و اون button19 رو از اون نوع قرار بدید و بعد OnClick رو در کلاسش Override کنید. وگرنه Button.OnClick که کدش ثابته، نمیشه تغییرش داد.
کلاسش رو باید Override کنید، شما کلاس Form1 رو تغییر میدید و OnClick ئه Form1 رو override می کنید، نه Form.OnClick ، حالا مشابهش باید در یک کلاس از Button ارث بری کنید و اون button19 رو از اون نوع قرار بدید و بعد OnClick رو در کلاسش Override کنید. وگرنه Button.OnClick که کدش ثابته، نمیشه تغییرش داد.
کلاسش رو باید Override کنید، شما کلاس Form1 رو تغییر میدید و OnClick ئه Form1 رو override می کنید، نه Form.OnClick ، حالا مشابهش باید در یک کلاس از Button ارث بری کنید و اون button19 رو از اون نوع قرار بدید و بعد OnClick رو در کلاسش Override کنید. وگرنه Button.OnClick که کدش ثابته، نمیشه تغییرش داد.

ممنون استاد علی
آها اصلا حواسم نبود . پس کلا وقتی رویدادی اجرا میشه (مثلا رویداد کلیک) ، اول متدی که با On شروع میشه و در control هست ، اجرا میشه (مثلا OnClick) و بعد این متد ، اون متدی که به اون رویداد وصل کردیم (مثلا Form1_Click) رو اجرا میکنه (به هر دلیلی این متد OnClick اجرا نشه ، نمیتونه رویداد مورد نظر را اجرا کنه)
حالا وقتی در کلاس Form1 ، اون متد OnClick را override میکنیم ، متد override شده ، یعنی همین متد OnClick در کلاس Form1 اجرا میشه (طبق قضیه ی شی گرایی) و اگه به هر دلیلی از این متد override شده ، نتونه متد پایه اش که در کلاس کنترل را فراخونی کنه ، متدی که به رویداد کلیک Form1 وصل کردیم را اجرا نمیکنه
حالا وقتی از Button ای شی میسازیم و رویداد کلیک اش اجرا میشه ، چون متد OnClick ای در کلاس Button یا فرزندان Button ، اورراید نشد ، پس مستقیما میره OnClick در کلاس کنترل را اجرا و بنابراین متدی که به رویداد کلیک شی Button وصل کردیم را اجرا میکنه (طبق شی گرایی)
 
آخرین ویرایش:

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ماشین مجازی مدام در حال کار ئه، متوقف که نشده. اگه کسی بهتون توصیه کرده باید برای آزاد کردن حافظه اشیاء بلااستفاده در NET. کاری انجام بدید و از GC.Collect استفاده کنید، معلومات زیادی نداشته. استاد که هیچی، کسی که یکبار توضیحات یک متد رو بخونه میفهمه که GC.Collect کاربرد عمومی در برنامه نویسی نداره و استفاده هاش خیلی محدود ئه.

کلا هدف تون کارآمد نیست، یعنی در برنامه نویسی کاربردی نداره. مثالش مثل کارواش میمونه، شما از لحظه ای که ماشین رو از کارواش دربیارید ماشین در حال کثیف شدنه، بعد تمیز شدنش با میکروسکوپ بررسی بشه باز ماشین تمیز از کارواش در نمیاد و روش گرد و خاک و دوده و چربی هست. تمیزی خوبه، پس باید ماشین هر ساعت دوباره بره کارواش؟ نه. نه منطقی ئه و نه مفید. کارواش رفتن هم استهلاک داره، هم هزینه داره و هم زمان بر ئه و هم جلوی استفاده ماشین رو میگیره. GC باید وقتی حافظه اشیاء بلااستفاده رو آزاد کنه که لازم و مفید باشه. این چیزی نیست که شما بتوانید یا لازم باشه تشخیص بدید یا در موردش دخالتی بکنید. GC هر لحظه که پروسه رو بررسی کنه، یکسری شیء بلا استفاده است که حافظه شون آزاد نشده. چون این پروسه در ماشین مجازی در حال کار ئه. مثل بدن انسان. هر لحظه که از حموم دربیایید هم پوشیده از چربی و باکتری و ویروس و ... ئه. بدن مدام هم عرق می کنه و هم چربی ترشح می کنه. اینکه ماشین مجازی هیچ شی بلا استفاده ای در حافظه نداشته باشه نه پایدار ئه، نه مفید ئه و نیازی هست که اینطور باشه. هم سربار داره، هم منابع سیستم رو تلف می کنه و هم فایده ای نداره. شما وقت ارزشمند سیستم رو تلف می کنید برای یکسری بایت هایی که آزاد شدنش هیچ کمکی نمی کنه. اگه فکر می کنید استفاده از GC.Collect مفید ئه اشتباه فکر می کنید. اگه کسی هم بهتون توصیه کرده اونم اشتباه فکر می کنه. ایراد از GC.Collect نیست که پروسه هنوز اشیاء بلاستفاده داره، کار اون ایرادی نداره، در جهت بهتر مدیریت کردن منابع ئه. اشکال از شما است. اینکه شما GC.Collect رو اجرا می کنید کار مفیدی نیست، مضر ئه. حالا وقت پردازنده رو میگیرید به کنار، یه WaitForPendingFinalizers هم به اون اضافه می کنید که پروسه خودتون هم معطل بشه. چه کاریه؟ وسواس ئه. نه کارایی پروسه تون رو بیشتر می کنه و نه سیستم عامل رو. کمکی هم به مدیریت منابع نمی کنه. اینکار تون فقط هدر دادن منابع ئه. تفکر تون نسبت به حافظه آزاد نشده شبیه وسواسی ها است، کیفیت برنامه نویسی بر اساس سهولت و سرعت و کارایی و انتقال پذیری و استفاده مجدد پذیری و ... سنجیده میشه، نه کاهش کارایی GC بخاطر وسواس بی فایده. حالا خودتون اینطوری فکر می کنید به کنار، انتقاد هم می کنید که چرا طوری نساختنش که بیشتر کند بشه و کارایی سیستم رو بهتر بیارید پایین؟

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

the_king

مدیرکل انجمن
ممنون استاد علی
بله این مطالب رو قبلا گفتین و میدونم
والا راضی به این همه نوشتن نیسم . ممنون
نه . کسی نگفت . خودم اصرار دارم
اول بذارین من قضیه ی سربار رو ازتون بپرسم . سربار دقیقا چیه؟ چد جا این کلمه را بار بردین . منظورتون زمان پردازش پردازنده که برای اون کار صرف میکنه هست؟
هر عملیاتی برای انجامش یکسری منابع رو درگیر می کنه، این منابعی که درگیر میشن جزو اهداف شما نیستند، سربار هستند. مثلا وقتی شما می خواهید فایلی رو فشرده کنید هدف تون کاهش حجم فایل ئه، اما هارد دیسک و پردازنده رو مشغول می کنید، سیستم کند میشه، سرعت پاسخ دهی اش کم میشه، استهلاک هارد دیسک ایجاد میشه، هیچکدوم اینها مطلوب نیست، ولی اینها سرباری هستند که برای فشرده سازی فایل ها مجبورید بپذیرید.
سربار یا Overload مختص پردازنده نیست، فرضا وقتی دیسک مرتب نیست و Fragment داره سربار روی دیسک ایجاد میشه برای کاوش تکه ها و یا سربار ایجاد میشه زمانی که برای مرتب سازی Defrag اش می کنیم. این سربار هیچوقت چیز خوبی نیست، اما گاهی به صرفه است و ارزش داره و گاهی نداره. فرضا مرتب سازی دیسکی که %1 ناقابل Fragment داره به صرفه نیست، اغلب برنامه های مرتب سازی هم این مساله رو رعایت می کنند، زمانی برای مرتب سازی سربار ایجاد می کنند که از این مرتب سازی اونقدر کارایی بدست بیاد که در مقابل استهلاک و سربار روی دیسک بیارزه.

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

میدونم مثل قضیه ی کارواش و حمام و... هست ولی مثلا یه بار میاد که در یه جایی ، خیلی حافظه مصرف میشه (مثلا همون کدی که دادم با تعداد اعضای آرایه های بسیار بالا (که در اون مثال ، 125 مگابایت از حافظه را مصرف کرد) . خوب وقتی که میخوام استفاده ام از این آرایه تمام شد و بهش نیازی ندارم ، چون رم زیادی هم اشغال میکنه ، حافظه اش را آزاد کنه تا سیستم عامل برای برنامه های دیگه اگه خواست ، به اون برنامه ها اختصاص بده ولی اگه دست خود GC باشه ، من فقط دیدم خودش بصورت اتوماتیک ، وقتی که مصرف حافظه برای اون پروسه ، وقتی بالای 2 گیگابایت رفت ، حافظه را آزاد میکنه
بهینه بودن برنامه ها مخصوصا توی این زمان و مخصوصا برای نرم افزارهای مهم ، در حداقل زمان ، به نظرم کار ضروری هه برای برنامه نویس ها (مثل نرم افزار آنتی ویروس ها . مثلا Avast ، تا جایی که یادم بیاد ، بالای 10 مگ در حالت عادی بیشتر مصرف نمیکنه و ...)
دقیقا مثال خودتون نشون میده که کجای کار اشتباهه. بهینه بودن برنامه در مصرف حافظه یعنی چی؟ یعنی از میزان حافظه ای که میگیره بهترین استفاده رو بکنه. نه اینکه کمترین حافظه ممکن رو بگیره و نه بیشترین حافظه ممکن رو بگیره و نه حافظه زیادی بگیره و بعد بخواد بزور پس بده. اگه پروسه شما با 2 برابر حافظه بیشتر پردازش اش چند برابر سریعتر میشه بهتره که اون حافظه رو بگیرید. اگه پروسه شما با نصف حافظه فعلی میتونه در همین حد کارایی کار کنه بهتره که نصف فعلی رو درخواست کنید. بهینه سازی یعنی این. ارتباط بین کارایی با حافظه مصرفی مطرحه، نه فقط میزان حافظه مصرفی. حافظه RAM خالی به هیچ دردی نمیخوره و هیچ مزیتی هم نداره. این رو قبلا هم گفتم.
و اگر میخواهید مصرف حافظه رو بیارید پایین، میزان درخواستی تون رو باید کم کنید، نه اینکه درخواست بدید و بعد زورکی پس بدید. یعنی اگر به نظرتون حافظه 125 مگابایتی درخواست زیادیه هیچوقت درخواست 125 مگابایت رو نکنید. وقتی شما از سیستم عامل درخواست این حافظه رو می کنید یا باید پروسه تون رو متوقف کنه به امید اینکه یک وقتی اون حافظه آزاد رو داشته باشه که بهتون بده یا از پروسه های دیگه اون حافظه رو بگیره و بهتون بده. در هر صورت اگه حافظه آزاد سیستم به اون حد نباشه شما سربار رو روی سیستم عامل ایجاد کرده اید و رفت پی کارش. دیگه امتیاز منفی از همون لحظه درخواست ثبت شده. چه زود پس اش بدید و چه دیر پس بدید از سایر پروسه ها بزور حافظه دریافت شده که به معنی سربار روی دیسک ئه. اگه 125 مگابایت رو حافظه زیادی میدونید، نباید اصلا درخواست اش کنید. و در ضمن حافظه اش رو آزاد کنه معنی اش چیه؟ معنی اش اینه که اون حافظه به حافظه های آزاد پروسه اضافه بشه نه اینکه برگرده به سیستم عامل. اینو قبلا هم بهتون گفتم. اینکه پروسه شما 125 مگابایت حافظه بلااستفاده داره برای شما منفعتی داره؟ قطعا خیر. سیستم عامل در اون لحظه بهش احتیاج داره؟ از کجا میدونید؟ اگه احتیاج داشته باشه که خودش میگیره. شما می توانید تشخیص بدید که کدوم پروسه هست که الان اولویت داره تا سیستم عامل باید ازش کمبود حافظه اش رو جبران کنه؟ مسلما نه. مطمئن باشید که GC کارش رو خیلی بهتر از شما انجام میده. و مطمئن باشید که سیستم عامل هیچوقت برای پس گرفتن حافظه از پروسه ها خجالت نمی کشه. لازم باشه میگیره. چه آزاد بکنید و چه نکنید. روالی که GC و سیستم مدیریت حافظه دارند از چیزی که شما بخواهید پیش بینی کنید بهتر عمل می کنه. اونها به اطلاعاتی دسترسی دارند که شما ندارید، و الگوریتم های اونها هم برای افزایش کارایی نوشته شده، نه زود بگیر زود پس بده ای که شما میخواهید اجرا کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
در ضمن حافظه اش رو آزاد کنه معنی اش چیه؟ معنی اش اینه که اون حافظه به حافظه های آزاد پروسه اضافه بشه نه اینکه برگرده به سیستم عامل. اینو قبلا هم بهتون گفتم. اینکه پروسه شما 125 مگابایت حافظه بلااستفاده داره برای شما منفعتی داره؟ قطعا خیر. سیستم عامل در اون لحظه بهش احتیاج داره؟ از کجا میدونید؟ اگه احتیاج داشته باشه که خودش میگیره. شما می توانید تشخیص بدید که کدوم پروسه هست که الان اولویت داره تا سیستم عامل باید ازش کمبود حافظه اش رو جبران کنه؟ مسلما نه. مطمئن باشید که GC کارش رو خیلی بهتر از شما انجام میده. و مطمئن باشید که سیستم عامل هیچوقت برای پس گرفتن حافظه از پروسه ها خجالت نمی کشه. لازم باشه میگیره. چه آزاد بکنید و چه نکنید. روالی که GC و سیستم مدیریت حافظه دارند از چیزی که شما بخواهید پیش بینی کنید بهتر عمل می کنه. اونها به اطلاعاتی دسترسی دارند که شما ندارید، و الگوریتم های اونها هم برای افزایش کارایی نوشته شده، نه زود بگیر زود پس بده ای که شما میخواهید اجرا کنید.

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

the_king

مدیرکل انجمن
ممنون استاد علی
درباره ی قسمت های بالاترکه توضیح دادین و نقل قول نکردم (سربار و ...) ، ممنون
ولی سئوالم در این تیکه هست
یعنی سیستم عامل ، خودش اتوماتیک ، حافظه رو از پروسه ها میگیره؟ حتی اگه متغییرش اشاره گر داشته باشه و قابلیت آزاد شدن نداشته باشه؟!! این جوری که ممکنه یه برنامه ای حداقل ارور بده

بله، سیستم عامل میتونه حتی کل حافظه یک پروسه رو بگیره و معلق اش کنه و هر وقت لازم شد هم مجددا حافظه رو بهش برگردونه و کارش رو ادامه بده، یا بخشی رو ازش بگیره و هر وقت مجددا به اون بخش نیاز پیدا کرد معلق اش کنه یا حافظه رو بهش برگردونه. اون خطایی که میگید برای برنامه رخ نمیده. در مورد paged memory و virtual memory و کلا مدیریت حافظه سیستم عامل مطالعه کنید متوجه میشید.

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

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

سئوال بعدی هم اینکه با پادویش درباره ی نحوه ی دسترسی یک پروسه به متغییرهای حافظه ی برنامه های دیگه صحبت میکردیم ، گفتن که بصورت عادی ، هر پروسه ای ، اشاره گر خودش را داره و سیسم عامل نمیذاره هیچ پروسه ای به مقادیر و اشاره گر پروسه های دیگه ، دسترسی داشته باشه . مثلا آدرس خونه ی 0x00567000 در پروسه ای یه مقدار باشه ، همین آدرس در پروسه ی دیگه ، فرق داره و ربطی به هم ندارن
جز با فناوری "حافظه ی مجازی"
یه چیزهایی رو جسته گریخته گفتن و با حافظه مجازی قاطی کردید یا اونها بد توضیح دادند. در هر صورت WinHex رو نصب کنید. منوی Tools از گزینه Open Memory استفاده کنید و محتویات حافظه پروسه ها رو ببینید، ربطی هم به حافظه مجازی نداره. همه سیستم ها الزاما حافظه مجازی ندارند، یعنی قابل غیر فعال سازیه. دسترسی به حافظه سایر پروسه ها در ویندوز های قدیمی مجوز نمیخواست و در ویندوز های جدید مجوز سیستم عامل رو میخواد، همونکاری که WinHex می کنه، Cheat Engine می کنه و ...
کلا حافظه فیزیکی به شکلی که فیزیکی آدرس دهی میشه صرفا در اختیار سیستم عامل ئه و هسته اش. یعنی اون آدرس فیزیکی رو در برنامه هاتون ندارید. چیزی که تحت عنوان آدرس دهی حافظه در برنامه هاتون دارید نسبی ئه. نسبت به موقعیت شروع برنامه خودتون در حافظه است. برای همین هم قابل جابجایی ئه و سیستم عامل میتونه موقعیت حافظه در اختیار پروسه رو تغییر بده. چون اگه آدرس ها مطلق بود که نمیشد هیچ تغییری در حافظه در اختیار پروسه داد. هر جابجایی صورت می گرفت آدرس داخل اشاره گر ها از اعتبار می افتاد. حالا این به کنار، برنامه شما که در ماشین مجازی NET. اجرا میشه خودش آدرس دهی خودشو داره، برای همین هم هست که مستقیما از محیط Managed با API حافظه رد و بدل نمیشه.

حالا میخواستم بدونم درباره ی این تکنولوژی حافظه ی مجازی و نحوه ی دسترسی به متغییرهای دیگر پروسه ها ، جمع آوری دانش مربوط بهش قدر طول میکشه؟
خیلی دوست دارم مباحث هک و ... رو هم سراغش برم (البته این سئوال فقط صرفا برای اینه که مدت زمان اش رو بدونم ولی خودم فعلا بخاطر مسائل شخصی فرصت ندارم)
چند سال وقت لازم دارید تا ساختار داخلی سیستم عامل ویندوز رو خوب بشناسید، کسی که یک سیستم عامل دیگه رو خوب بشناسه، قطعا زمان کمتری لازم داره چون یکسری مباحث مشترک ئه. و خیلی تفاوت هست بین کسی که برای ویندوز با #C یا Delphi برنامه کاربردی می نویسه با کسی که ساختار سیستم عامل رو میشناسه و فرضا روال فعال سازی ویندوز رو تغییر میده یا برای یک سخت افزار جدید درایور می نویسه. دو تا دانش مستقل هستند با یکسری معلومات مشترک. برای کسی که برای ویندوز برنامه می نویسه اینکه فایل EXE و PE چه ساختاری داره یا حافظه پروسه چطور مدیریت میشه اهمیتی نداره، چون درگیر ساختار داخلی سیستم عامل نیست. اما برای کسی که میاد فرضا چیزی مثل UPX می نویسه که حافظه فایل EXE رو فشرده می کنه، دانستن این چیزا مهمه. مباحثی که میگید ربطی به هک کردن نداره، نفوذ به سیستم عامل یک بحث گسترده است که سر و ته هم نداره و هیچوقت هم تموم نمیشه، چون مدام باید از سد های جدید عبور کنید. بیشتر هم درگیر مباحث شبکه و رمز گشایی و ... است چون از راه دور ئه، پای خود سیستم که نمیاد. دانش مثبتی هم نیست که کسی بخواد افتخار کنه که هکر ئه، چه کلاه سفیدش چه کلاه سیاهش. هکر از نظر روانی آدم نرمالی نیست، یا عقده جلب توجه داره یا ذهن مخربی داره، به حریم بقیه تجاوز می کنه، شخصیت محترمی نیست. اینهم که میگن هکر میشن که بعدا در شرکت ها مشاوره امنیتی بدن حرف بی ربطی ئه. لزومی نداره کسی هکر باشه تا بتونه در سیستم های امنیتی کارشناسی کنه. کسی که جلیقه ضد گلوله میسازه لازم نیست تیراندازی بلد باشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله، سیستم عامل میتونه حتی کل حافظه یک پروسه رو بگیره و معلق اش کنه و هر وقت لازم شد هم مجددا حافظه رو بهش برگردونه و کارش رو ادامه بده، یا بخشی رو ازش بگیره و هر وقت مجددا به اون بخش نیاز پیدا کرد معلق اش کنه یا حافظه رو بهش برگردونه. اون خطایی که میگید برای برنامه رخ نمیده. در مورد paged memory و virtual memory و کلا مدیریت حافظه سیستم عامل مطالعه کنید متوجه میشید.
ممنون استاد علی
آها پس واسه ی همین بود همش تاکید میکردین که نیاز به استفاده از GC.Collect نیست؟
ولی اگه سیستم عامل ، اون متغییرهایی که اشاره گر دارن رو هم بخواد خودسر بگیره ، خوب موقع فراخونی اون متغییر ، ارور NullRefrence برای برنامه میده
یعنی منظورم اینه که باید روال خاصی داشته باشه دیگه . درسته؟ نمیشه که متغییرهای اشاره گر دار رو به زور پس بگیره . میشه؟! یا فقط متغییرهای بدون اشاره گر را پس میگیره؟


یه چیزهایی رو جسته گریخته گفتن و با حافظه مجازی قاطی کردید یا اونها بد توضیح دادند. در هر صورت WinHex رو نصب کنید. منوی Tools از گزینه Open Memory استفاده کنید و محتویات حافظه پروسه ها رو ببینید، ربطی هم به حافظه مجازی نداره. همه سیستم ها الزاما حافظه مجازی ندارند، یعنی قابل غیر فعال سازیه. دسترسی به حافظه سایر پروسه ها در ویندوز های قدیمی مجوز نمیخواست و در ویندوز های جدید مجوز سیستم عامل رو میخواد، همونکاری که WinHex می کنه، Cheat Engine می کنه و ...
کلا حافظه فیزیکی به شکلی که فیزیکی آدرس دهی میشه صرفا در اختیار سیستم عامل ئه و هسته اش. یعنی اون آدرس فیزیکی رو در برنامه هاتون ندارید. چیزی که تحت عنوان آدرس دهی حافظه در برنامه هاتون دارید نسبی ئه. نسبت به موقعیت شروع برنامه خودتون در حافظه است. برای همین هم قابل جابجایی ئه و سیستم عامل میتونه موقعیت حافظه در اختیار پروسه رو تغییر بده. چون اگه آدرس ها مطلق بود که نمیشد هیچ تغییری در حافظه در اختیار پروسه داد. هر جابجایی صورت می گرفت آدرس داخل اشاره گر ها از اعتبار می افتاد. حالا این به کنار، برنامه شما که در ماشین مجازی NET. اجرا میشه خودش آدرس دهی خودشو داره، برای همین هم هست که مستقیما از محیط Managed با API حافظه رد و بدل نمیشه.


چند سال وقت لازم دارید تا ساختار داخلی سیستم عامل ویندوز رو خوب بشناسید، کسی که یک سیستم عامل دیگه رو خوب بشناسه، قطعا زمان کمتری لازم داره چون یکسری مباحث مشترک ئه. و خیلی تفاوت هست بین کسی که برای ویندوز با #C یا Delphi برنامه کاربردی می نویسه با کسی که ساختار سیستم عامل رو میشناسه و فرضا روال فعال سازی ویندوز رو تغییر میده یا برای یک سخت افزار جدید درایور می نویسه. دو تا دانش مستقل هستند با یکسری معلومات مشترک. برای کسی که برای ویندوز برنامه می نویسه اینکه فایل EXE و PE چه ساختاری داره یا حافظه پروسه چطور مدیریت میشه اهمیتی نداره، چون درگیر ساختار داخلی سیستم عامل نیست. اما برای کسی که میاد فرضا چیزی مثل UPX می نویسه که حافظه فایل EXE رو فشرده می کنه، دانستن این چیزا مهمه. مباحثی که میگید ربطی به هک کردن نداره، نفوذ به سیستم عامل یک بحث گسترده است که سر و ته هم نداره و هیچوقت هم تموم نمیشه، چون مدام باید از سد های جدید عبور کنید. بیشتر هم درگیر مباحث شبکه و رمز گشایی و ... است چون از راه دور ئه، پای خود سیستم که نمیاد. دانش مثبتی هم نیست که کسی بخواد افتخار کنه که هکر ئه، چه کلاه سفیدش چه کلاه سیاهش. هکر از نظر روانی آدم نرمالی نیست، یا عقده جلب توجه داره یا ذهن مخربی داره، به حریم بقیه تجاوز می کنه، شخصیت محترمی نیست. اینهم که میگن هکر میشن که بعدا در شرکت ها مشاوره امنیتی بدن حرف بی ربطی ئه. لزومی نداره کسی هکر باشه تا بتونه در سیستم های امنیتی کارشناسی کنه. کسی که جلیقه ضد گلوله میسازه لازم نیست تیراندازی بلد باشه.

ممنون استاد علی
آها ، بخاطر فضای آدرس دهی متفاوت هست که Managed کدها (دات نت) با UnManaged ها متفاوت ان؟
بله . شاید من قشنگ متوجه نشده باشم ولی متن دقیق شون این بود (قضیه اش درباره ی حملات رسانه ی اخیر در تخریب پادویش بود که ماجرا داره ....) :

--------------------------------------------------------------
نوشتن در حافظه پردازه دیگر به صورت عادی امکانپذیر نیست (یعنی از طریق اشاره‌گر عادی انجام نمی‌شود) در تمام سیستم عامل‌های جدید (بعد از سال ۲۰۰۰) فضای آدرس حافظه هر پردازه از سایر پردازه‌ها کاملا جدا است.

مثال: اگر خانه شماره 0x00567000 در پردازه الف فلان محتوا را دارد و مثلا رشته خاصی در آن ذخیره شده است. اما همین آدرس 0x00567000 در پردازه ب مقدار متفاوتی دارد. هیچ پردازه‌ای قادر به خواندن یا نوشتن در حافظه پردازه‌های دیگر نیست.

این کار به کمک مفهوم حافظه مجازی (Virtual Memory) انجام می‌شود. احتمالا شنیده‌اید که حافظه مجازی اجازه می‌دهد که سیستم عامل بخشی از رم را به دیسک منتقل کند و در شرایط کمبود حافظه بهتر کار کند. اما کارکرد دیگر (و اصلی) حافظه مجازی این است که آدرس‌های حافظه که در هر پردازه دیده می‌شود مجازی است. یعنی آدرس خانه 0x00567000 آدرس فیزیکی حافظه رم شما نیست، بلکه توسط سی‌پی‌یو به آدرس حافظه فیزیکی (که ممکن است هر چیزی باشد و حتی به دستور سیستم عامل جابجا شده و تغییر کند) ترجمه می‌شود. در نتیجه هر برنامه فضای حافظه‌ای متفاوت خودش را دارد و هر کس بخش متفاوتی از رم را به عنوان آدرس 0x00567000 خواهد دید.
تا پیش از فناوری حافظه مجازی (مثلا سیستم عامل داس یا ویندوز ۹۵)، هر برنامه‌ای کل رم را می‌دید و باید مواظب می‌بود که فضایی غیر از حافظه خودش را تغییر ندهد، وگرنه منجر به اختلال و کرش کل سیستم می‌شد. در صورتیکه با این فناوری، هر برنامه در یک فضای مجازی فعالیت می‌کند که از تاثیر سایر برنامه‌ها در امان است و بدترین کاری که می‌تواند بکند صرفا اختلال و کرش خودش است و به دیگران آسیبی نخواهد رسید.

اما روش‌های نوشتن/خواندن حافظه سایر پردازه‌ها از طریق توابعی کرنلی انجام می‌گیرد که ابتدا دسترسی شما را چک کرده و به شما اجازه خرابکاری را نمی‌دهند. مثلا دو تابع WriteProcessMemory و ReadProcessMemory به شما (در صورت داشتن حق دسترسی) اجازه می‌دهند حافظه یک پردازه دیگر را بخوانید یا بنویسید. این توابع در اصل برای ابزارهایی مثل دیباگرها کاربرد دارد که موقع برنامه‌نویسی به شما کمک می‌کنند حین اجرای برنامه آن را دیباگ کرده و مقدار فلان متغیر را ببینید یا تغییر دهید.
طبیعتا اجرای چنین توابعی روی پروسه پادویش (حتی اگر ادمین باشید) امکان پذیر نیست، مگر اینکه محافظت از خود پادویش را غیرفعال یا خراب کنید.
--------------------------------------------------------------

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

the_king

مدیرکل انجمن
ممنون استاد علی
آها پس واسه ی همین بود همش تاکید میکردین که نیاز به استفاده از GC.Collect نیست؟
ولی اگه سیستم عامل ، اون متغییرهایی که اشاره گر دارن رو هم بخواد خودسر بگیره ، خوب موقع فراخونی اون متغییر ، ارور NullRefrence برای برنامه میده

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

یعنی منظورم اینه که باید روال خاصی داشته باشه دیگه . درسته؟ نمیشه که متغییرهای اشاره گر دار رو به زور پس بگیره . میشه؟! یا فقط متغییرهای بدون اشاره گر را پس میگیره؟
قبلا هم بهتون گفتم، سیستم عامل فقط page میده و page پس میگیره، متغیر و اشاره گر چیزی نیست که سیستم عامل ازش خبر دار باشه و یا بهشون اهمیت بده، از نظر سیستم عامل page محتوی یکسری بایت ئه که نه میدونه مربوط به چیه و نه اهمیتی میده که چه فرمتی داره، page برای سیستم عامل فقط یکسری داده است. فضای استفاده شده و نشده داخل page هم برای سیستم عامل تفکیک نشده.

ممنون استاد علی
آها ، بخاطر فضای آدرس دهی متفاوت هست که Managed کدها (دات نت) با UnManaged ها متفاوت ان؟

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

بله . شاید من قشنگ متوجه نشده باشم ولی متن دقیق شون این بود (قضیه اش درباره ی حملات رسانه ی اخیر در تخریب پادویش بود که ماجرا داره ....) :

نه، کسی که این توضیحات رو بهتون داده ساختار ویندوز رو خوب نمی شناسه، فرق آدرس دهی مجازی رو با حافظه مجازی نمیدونه، تفاوت Real Mode و Protected Mode رو درست نمیدونه. یک چیزهایی درست و نادرستی رو قاطی کرده، نه ویندوز 95 اونطوریه که ایشون فکر می کنه و نه اساسا برنامه های ویندوز بدون آدرس های نسبی میتوانستن در ویندوز 95 اجرا بشن و نه دسترسی به حافظه سایر برنامه ها در ویندوز های قدیمی اینقدر بی در و پیکر بوده و نه این قضیه ربطی به سال 2000 و ویندوز های مدرن داره و نه چیزی که با لینک Virtual memory بهتون داده مرتبط با این قضیه است. اون Windows 3.1 که بابابزرگ Windows 95 ئه هم در Protected Mode کار می کرد چه برسه به ویندوز های بعدی. صحبت کی ئه؟ 1990، خیلی قبل تر از ویندوز 95. چند تا مساله متفاوت رو با هم قاطی کرده. حداقل به عنوان منبع علمی و اطلاعات عمومی و فنی روی ایشون حساب نکنید، چیزی رو ندونستن بهتر از اطلاعات نادرست ئه. ویندوز از همون ابتدا بر اساس Protected Mode اجرا میشده که هر پروسه ای حافظه اش مستقل ئه، چه ربطی به Virtual Memory داره.

الان اون نرم افزار WinHex ، از همین دو تابعی که گفتن ، برای نمایش اطلاعات فیزیکی حافظه استفاده میکنه؟
حالا اگه برنامه ای بتونه اطلاعات حافظه ی دیگر پروسه ها را بخونه ، روند کلی اش چجوری هه؟ یعنی اولا چجوری تشخیص میده که چه آدرس فیزیکی ای ، برای کدوم پروسه هست؟ بعد حالا که تشخیص داد ، چجوری به متغییرها و کلا سطح درایور یا هسته ی اون پروسه نفوذ میکنه و چجوری میتونه باعث کرش شدنش بشه؟
میتوانند از اون تابع ها استفاده کنند، میتوانند از یک درایور واسطه استفاده کنند، از امکانات سایر ابزار هایی که این قابلیت رو دارند استفاده کنند، از شکاف های امنیتی سیستم استفاده کنند و ...
برنامه که با آدرس فیزیکی کار نداره، حافظه یک پروسه رو باز می کنه، پروسه مشخصه و حافظه پروسه مستقل ئه، قاطی حافظه بقیه پروسه ها نیست که دنبال آدرس فیزیکی چیزی بگرده. ربطی هم به هسته سیستم عامل نداره، سیستم عامل هسته اش یک حافظه است، حافظه برنامه های عادی یک حافظه دیگه. اینو قبلا هم در بحث 32 و 64 بیتی بودن گفته بودم. کلا محیط اجرای برنامه عادی با محیطی که درایور ها در اون اجرا می شوند جداست.

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

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

SajjadKhati

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


کد:
        private void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (this.VerticalScroll.Visible == true)
            {
                //this.SuspendLayout();
                ScrollEventArgs scrollEvent = new ScrollEventArgs(ScrollEventType.ThumbTrack, this.VerticalScroll.Value, ScrollOrientation.VerticalScroll);
                this.Form1_Scroll(this, scrollEvent);
            }
        }

        private void Form1_Scroll(object sender, ScrollEventArgs e)
        {
            this.lblText.Text = e.NewValue.ToString();
            this.lblText2.Text = e.ScrollOrientation.ToString();
            this.lblText3.Text = e.Type.ToString();
        }

ولی وقتی چرخ موس را حرکت میدم ، اگه اون کدی که در رویداد Form1_MouseWheel کامنت شده هست ، اجرا نشه (بصورت کامنت باشه) ، اسکرول در فرم ، برمیگرده به حالت اولیه ی خودش (برمیگرده به بالا) ولی اگه از کامنت در بیاد درست میشه ولی باز مشکلی که پیش میاد اینه که وقتی فرم را resize میکنیم ، در این صورت ، اغلب اوقات ، اسکرول فرم با resize کردن ، ثابت میمونه تا اینکه روی اسکرول کلیک بشه تا درست بشه
اگه سر آخر (در پایان رویداد Form1_MouseWheel) کد this.ResumeLayout(); رو بذاریم ، باز مشکل اول برمیگرده
کلا باید چجوری تغییرش داد؟
 

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
میگم من در فرم ام ، کد زیر را نوشتم :


کد:
        private void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (this.VerticalScroll.Visible == true)
            {
                //this.SuspendLayout();
                ScrollEventArgs scrollEvent = new ScrollEventArgs(ScrollEventType.ThumbTrack, this.VerticalScroll.Value, ScrollOrientation.VerticalScroll);
                this.Form1_Scroll(this, scrollEvent);
            }
        }

        private void Form1_Scroll(object sender, ScrollEventArgs e)
        {
            this.lblText.Text = e.NewValue.ToString();
            this.lblText2.Text = e.ScrollOrientation.ToString();
            this.lblText3.Text = e.Type.ToString();
        }

ولی وقتی چرخ موس را حرکت میدم ، اگه اون کدی که در رویداد Form1_MouseWheel کامنت شده هست ، اجرا نشه (بصورت کامنت باشه) ، اسکرول در فرم ، برمیگرده به حالت اولیه ی خودش (برمیگرده به بالا) ولی اگه از کامنت در بیاد درست میشه ولی باز مشکلی که پیش میاد اینه که وقتی فرم را resize میکنیم ، در این صورت ، اغلب اوقات ، اسکرول فرم با resize کردن ، ثابت میمونه تا اینکه روی اسکرول کلیک بشه تا درست بشه
اگه سر آخر (در پایان رویداد Form1_MouseWheel) کد this.ResumeLayout(); رو بذاریم ، باز مشکل اول برمیگرده
کلا باید چجوری تغییرش داد؟
من از کجا باید بدونم شما می خواهید چیکار کنید؟ چیزی که من الان می بینم که شما با ساختن دستی رخداد Scroll روال عادی رو مختل می کنید تا مشابه روال عادی اش عمل نکنه. حالا با چه هدفی، نمیدونم. باید بگید که بدونم هدف چیه.
 

SajjadKhati

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

ممنون
میخوام وقتی چرخ موس را میگردونم ، رویداد Form1_Scroll اجرا بشه
 

the_king

مدیرکل انجمن
ممنون
میخوام وقتی چرخ موس را میگردونم ، رویداد Form1_Scroll اجرا بشه
رخدادی که شما میخواهید یک چیزی مثل vScrollBar1_ValueChanged ئه که برای ScrollBar فرم وجود نداره. دلیلش اینه که اصلا مثل VScrollBar پنجره مستقل نداره که همچین رخداد هایی رو ایجاد کنه، جزئی از پنجره خود فرم ئه. برای همین در رخداد های پنجره هم تغییر مقدار VSCROLL چیزی نیست که براش پیغامی ایجاد بشه، یعنی نه Scroll و نه MouseWheel دقیقا چیزی نیست که به تغییر مقدار VScroll مربوط باشه. ساده ترین کاری که می توانید بکنید اینه که سه تا پیغامی که قاعدتا موقع تغییر مقدارش رخ داده اند رو بررسی کنید، احتمال داره که تغییر مقدار داخل اونها رخ بده. حتی می توانید مقدار قبلی رو جایی نگهداری کنید تا فقط وقتی کاری رو انجام بدید که واقعا مقدار عوض شده باشه :
کد:
        private const int WM_VSCROLL = 0x115;
        private const int WM_MOUSEWHEEL = 0x20A;
        private const int WM_SIZE = 0x5;

        private int _prevVerticalScroll;

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            switch (m.Msg)
            {
                case WM_VSCROLL:
                case WM_MOUSEWHEEL:
                case WM_SIZE:
                    if (_prevVerticalScroll != VerticalScroll.Value)
                    {
                        _prevVerticalScroll = VerticalScroll.Value;
                        VerticalScrollChanged();
                    }
                    break;
            }
        }

        private void VerticalScrollChanged()
        {
            this.lblText.Text = VerticalScroll.Value.ToString();
        }
 

SajjadKhati

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


کد:
        private void panel1_DragDrop(object sender, DragEventArgs e)
        {
            DataObject objectDraged = e.Data as DataObject;
            this.panel1.Controls.Add((Button)objectDraged.GetData(typeof(Button)));
        }

        private void panel1_DragEnter(object sender, DragEventArgs e)
        {
            DataObject objectDraged = e.Data as DataObject;
           
           
            if (objectDraged.GetDataPresent(typeof(Button)) == true)
                e.Effect = DragDropEffects.Move;
            else
                e.Effect = DragDropEffects.None;
        }

        private void Buttons_MouseDown(object sender, MouseEventArgs e)
        {
            Button button = sender as Button;
            this.DoDragDrop(button, DragDropEffects.All);  // باعث انجام عمل درگ و دروپ میشه
        }

کد بالا برای درگ کردن دکمه هایی که در فرم وجود داره برای دروپ کردن در پنل هست که مشکلی نداره
ولی مسئله اینجاست که اگه انواع مختلف کنترل مثل دکمه و لیبل و ... (و کلا هر کنترلی) رو در فرم داشته باشم و بخوام به پنل ام درگ و دروپ کنم ، باید برای تک تک این انواع ، کد بنویسم . باید چجوری کد بالا را تغییر بدم تا لازم به نوشتن کد جدید برای نوع کنترل جدید نباشه؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بعد اینکه چرا وقتی روی دکمه ای کلیک میکنم ، همزمان رویداد MouseDown و MouseLeave با هم اجرا میشن؟
اصلا از روی دکمه خارج نمیشم . ولی نمیدونم چرا رویداد MouseLeave هم اجرا میشه . تازه وقتی کلیک میکنم ، رویداد MouseLeave زودتر هم اجرا میشه !
چجوری میشه این دو رویداد بصورت واقعی و در زمان واقعی خودشون اتفاق بیافتن و زمان اجراشون از هم جدا باشن و با هم اجرا نشن؟
 

the_king

مدیرکل انجمن
ممنون استاد علی
توی فرم ام ، یک کنترل پنل بنام panel1 دارم و چندین دکمه که رویداد MouseDown همه ی دکمه ها را به متد Buttons_MouseDown در کد زیر وصل کردم :


کد:
        private void panel1_DragDrop(object sender, DragEventArgs e)
        {
            DataObject objectDraged = e.Data as DataObject;
            this.panel1.Controls.Add((Button)objectDraged.GetData(typeof(Button)));
        }

        private void panel1_DragEnter(object sender, DragEventArgs e)
        {
            DataObject objectDraged = e.Data as DataObject;
          
          
            if (objectDraged.GetDataPresent(typeof(Button)) == true)
                e.Effect = DragDropEffects.Move;
            else
                e.Effect = DragDropEffects.None;
        }

        private void Buttons_MouseDown(object sender, MouseEventArgs e)
        {
            Button button = sender as Button;
            this.DoDragDrop(button, DragDropEffects.All);  // باعث انجام عمل درگ و دروپ میشه
        }

کد بالا برای درگ کردن دکمه هایی که در فرم وجود داره برای دروپ کردن در پنل هست که مشکلی نداره
ولی مسئله اینجاست که اگه انواع مختلف کنترل مثل دکمه و لیبل و ... (و کلا هر کنترلی) رو در فرم داشته باشم و بخوام به پنل ام درگ و دروپ کنم ، باید برای تک تک این انواع ، کد بنویسم . باید چجوری کد بالا را تغییر بدم تا لازم به نوشتن کد جدید برای نوع کنترل جدید نباشه؟
خوب چه کاریه روی Button تنظیم اش می کنید. Control درگ کنید. هر شیء ای Label یا Button یا TextBox باشه به هر حال Control ئه، هم درست Drag میشه و هم درست Add میشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خوب چه کاریه روی Button تنظیم اش می کنید. Control درگ کنید. هر شیء ای Label یا Button یا TextBox باشه به هر حال Control ئه، هم درست Drag میشه و هم درست Add میشه.

ممنون
متوجه ی منظورتون نشدم
یعنی کد رو باید چجوری تغییر بدم؟
توی رویداد panel1_DragEnter در ورودی تابع objectDraged.GetDataPresent نوع typeof(Control) رو میدم ولی هر نوع کنترلی رو درگ میکنم ، نمیشناسه . فقط باید دقیق همون نوع کلاسِ کنترل (مثل Button) را بنویسم
 

the_king

مدیرکل انجمن
بعد اینکه چرا وقتی روی دکمه ای کلیک میکنم ، همزمان رویداد MouseDown و MouseLeave با هم اجرا میشن؟
اصلا از روی دکمه خارج نمیشم . ولی نمیدونم چرا رویداد MouseLeave هم اجرا میشه . تازه وقتی کلیک میکنم ، رویداد MouseLeave زودتر هم اجرا میشه !
چجوری میشه این دو رویداد بصورت واقعی و در زمان واقعی خودشون اتفاق بیافتن و زمان اجراشون از هم جدا باشن و با هم اجرا نشن؟
یک پروژه جدید بسازید، یک Button و یک ListBox داخل فرم اش قرار بدید و ترتیب رویداد ها رو بررسی کنید :
کد:
        private void button1_MouseEnter(object sender, EventArgs e)
        {
            listBox1.Items.Add("MouseEnter");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            listBox1.Items.Add("MouseClick");
        }

        private void button1_MouseLeave(object sender, EventArgs e)
        {
            listBox1.Items.Add("MouseLeave");
        }
        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            listBox1.Items.Add("MouseDown");
        }
اگه MouseDown و MouseLeave همزمان اجرا شدند یا MouseLeave با Click تداخل داشت، اونوقت این سوال رو بکنید، وگرنه اگر فقط برای یک کد خاص که نوشتید مشکلی پیش میاد، سوال تون کلی نیست که بدون کد قابل جواب دادن باشه، برای کدی که خودتون نوشتید و کسی بدون علم غیب نمی تونه ببینه نمیشه جوابی داد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک پروژه جدید بسازید، یک Button و یک ListBox داخل فرم اش قرار بدید و ترتیب رویداد ها رو بررسی کنید :
کد:
        private void button1_MouseEnter(object sender, EventArgs e)
        {
            listBox1.Items.Add("MouseEnter");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            listBox1.Items.Add("MouseClick");
        }

        private void button1_MouseLeave(object sender, EventArgs e)
        {
            listBox1.Items.Add("MouseLeave");
        }
        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            listBox1.Items.Add("MouseDown");
        }
اگه MouseDown و MouseLeave همزمان اجرا شدند یا MouseLeave با Click تداخل داشت، اونوقت این سوال رو بکنید، وگرنه اگر فقط برای یک کد خاص که نوشتید مشکلی پیش میاد، سوال تون کلی نیست که بدون کد قابل جواب دادن باشه، برای کدی که خودتون نوشتید و کسی بدون علم غیب نمی تونه ببینه نمیشه جوابی داد.
ممنون
یه دکمه با رویدادهای زیر :

کد:
        private void button24_MouseDown(object sender, MouseEventArgs e)
        {
            MessageBox.Show("Down");
        }

        private void button24_MouseLeave(object sender, EventArgs e)
        {
            MessageBox.Show("Leave");
        }

من که روش کلیک میکنم ، هم زمان ، هر دو رویداد اجرا میشه و اتفاقا MouseLeave زودتر اجرا میشه
 

the_king

مدیرکل انجمن
ممنون
متوجه ی منظورتون نشدم
یعنی کد رو باید چجوری تغییر بدم؟
توی رویداد panel1_DragEnter در ورودی تابع objectDraged.GetDataPresent نوع typeof(Control) رو میدم ولی هر نوع کنترلی رو درگ میکنم ، نمیشناسه . فقط باید دقیق همون نوع کلاسِ کنترل (مثل Button) را بنویسم
کد:
        private void panel1_DragDrop(object sender, DragEventArgs e)
        {
            this.panel1.Controls.Add((Control)e.Data.GetData(e.Data.GetFormats()[0]));
        }

        private void panel1_DragEnter(object sender, DragEventArgs e)
        {
            var x = e.Data.GetData(e.Data.GetFormats()[0]);
            e.Effect = (x is Control) ? DragDropEffects.Move : DragDropEffects.None;
        }

        private void Controls_MouseDown(object sender, MouseEventArgs e)
        {
            this.DoDragDrop(sender, DragDropEffects.All);  // باعث انجام عمل درگ و دروپ میشه
        }
 

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

بالا