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

the_king

مدیرکل انجمن
خیلی ممنون استاد.
بعد بهتر نیست که کنترل TransparentControl ، زمانی که dispose شد ، من اون رو از کنترل والدش Remove هم کنم؟
یعنی :
کد:
this.Parent.Controls.Remove(this);
نه. اینکار بصورت خودکار برای کمپوننت ها و کنترل ها انجام میشه.


خیلی ممنون استاد.
الان یعنی اگه یه پروپرتیِ dispose شدنی ای ، مقدار داشت (مقدار جدید بهش دادم) ، بعد ، مقدارش عوض شد (مقدار عوض شده ، چه میخواد null باشه یا یه شیِ دیگه) ، همون زمان که شی اش عوض میشه ، شیِ قبلی اش را dispose نکنم ؟
اگر شیء قبلی رو شما ساخته بودید Dispose اش می کنید و اگر شیء قبلی رو شما نساخته بودید Dispose نمی کنید. به همین سادگی.

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

من توی پروپرتی های dispose شدنی در هر 3 کلاس (زمانی که مقدارش عوض میشه) ، مقدار قبلی را dispose کردم .
بعد از اون ، زمان دیزاینر یه ارورهای عجیب و قریبی میده . اصلا به شی جدید ، کاری ندارم. قبل از اضافه کردنِ کدهای dispose ، این ارورها نبود.
اما موقعی که همون عملیات را بصورت کدنویسی انجام میدم ، اروری نمیده!!
ارورهاش هم مختلف هه ولی اغلب یه ارور کوتاه هه که میگه پارامتر اش invalidate هه . حالا کجا و کدوم پارامتر را نمیگه. باید چیکار کنم؟
الان منظور شما ، روش بالایی بود؟ روش بالایی رو برم؟
اولا استفاده از try catch رو فراموش نکنید، ثانیا شما فرضا رخدادی رو به روتین داخل شیء ای متصل می کنید که اگر فلان شد این متد اجرا بشه، حالا اگر شیء رو Dispose کنید، همچنان روتین میتونه اجرا بشه و ممکنه داخل روتین کاری انجام بدید که بخاطر Dispose شدنش دیگه قابل انجام نباشه.

استاد ، همونطور که شما گفتین ، فقط موقعی که متد dispose اجرا میشه ، اون اشیاء ها را dispose کردم و مشکل اون ارور برطرف شد.
توی کدهای designer (کدهای Editor) هم لازمه که شی های جدیدی که میذارم را dispose کنم؟
چون دیگه موقع طراحی که نرم افزاری که برنامه نویس نوشت ، اجرا نیست . طرف ، نرم افزار را طراحی میکنه و بعد ویژال استودیو رو میبنده و سیستم را خاموش میکنه که همه ی اطلاعات از حافظه پاک میشه.
نه، شما Dispose شون نمی کنید. اون اشیاء توسط Designer ذخیره میشه و دفعات بعدی توسط کدی که Designer نوشته، ایجاد میشه و مسئولیت Dispose شدنش هم با خودشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نه، شما Dispose شون نمی کنید. اون اشیاء توسط Designer ذخیره میشه و دفعات بعدی توسط کدی که Designer نوشته، ایجاد میشه و مسئولیت Dispose شدنش هم با خودشه.

سلام استاد.
خیلی ممنون.
منظورم از Editor ، کدهایی که در کلاس های TransparentControlBitmapEditor و TransparentControlBitmapEditorForm نوشتم ، هست.
لازم نیست کنترل ها و کلا کمپوننت هایی که توشون new میکنم را dispose کنم؟
-------
و یه سئوالی که تعجب مرا برانگیخت اینه که دیزاینر ویژال استودیو ، همه ی کنترل ها و کمپوننت هایی که مینویسه (و قابل dispose کردن هستند) را فقط با متد Dispose ای که در Form1.Designer.cs ای که مینویسه به همراه کدِ
کد:
this.components = new System.ComponentModel.Container();
ای که درون متد InitializeComponent مینویسه ، متوجه میشه که چه کمپوننت هایی را میخواد dispose کنه؟!!
اگه آره ، روند کارکردش چجوری هه؟
الان در کد بالا وقتی شی ای از کلاس Container ساخت ، خوب ، بعدش ، توسط متد Add ، کنترلی را بهش اضافه نکرد.
پس سر آخر ، وقتی اون اورلود متد Dispose (درون کلاس Form1.Designer.cs) ، چجوری میفهمه که کدوم کمپوننت ها و کنترل ها را باید dispose کنه؟
و سر آخر ، چرا در Program.cs ، بعد از کد Application.Run ، اون فرم ای که نمایش داد را dispose نمیکنه؟
اگه dispose کردن ، به همین سادگی هست ، پس چرا ما برای dispose کردن ، list ای از IDisposable درست کنیم و هر بار که شیِ جدیدِ قابلی dispose کردنی ای را میسازیم ، اون شی را به این لیست اضافه میکنیم؟ خوب ، ما هم این روش اش را بریم ها.

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

من همیشه متد dispose کردن را با آزاد کردنِ کل حافظه ی managed مربوط به اون شی ، قاتی میکردم . :) فکر میکردم وقتی dispose میکنیم ، کنترل مون ناپدید میشه ، پس شبیه به gc عمل میکنه و همه ی منابع را از حافظه پاک میکنه . واسه ی همین ، همیشه تعجب میکردم که اگه gc هست ، پس dispose واسه چی هست .
الان یه کم بیشتر متوجه شدم . دات نت برای کنترل هاشون و کلا کمپوننت هاشون ، در بخشی از کدهاشون ، از api ویندوز استفاده میکنند . api ویندوز هم از زبان ++C استفاده میکنند که میدونیم unmanaged هستند . وقتی dispose میکنیم ، این منابع api های ویندوز (که unmanaged هستند) را از حافظه پاک میکنند.
درسته دیگه؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام استاد.
خیلی ممنون.
منظورم از Editor ، کدهایی که در کلاس های TransparentControlBitmapEditor و TransparentControlBitmapEditorForm نوشتم ، هست.
لازم نیست کنترل ها و کلا کمپوننت هایی که توشون new میکنم را dispose کنم؟
متوجه منظورتون شده بودم، نه اون شما اون شیء که هایی که در TransparentControlBitmapEditor و TransparentControlBitmapEditorForm میسازید رو هر بار که کنترل ساخته میشه که اجرا نمی کنید، میسپارید به Designer که ذخیره کنه و با کدی که Designer میسازه بازتولید میشه، Dispose کردنش رو هم میسپارید به Designer.

-------
و یه سئوالی که تعجب مرا برانگیخت اینه که دیزاینر ویژال استودیو ، همه ی کنترل ها و کمپوننت هایی که مینویسه (و قابل dispose کردن هستند) را فقط با متد Dispose ای که در Form1.Designer.cs ای که مینویسه به همراه کدِ
کد:
this.components = new System.ComponentModel.Container();
ای که درون متد InitializeComponent مینویسه ، متوجه میشه که چه کمپوننت هایی را میخواد dispose کنه؟!!
نه اون components ربطی به Dispose شدن کنترل های روی فرم نداره. کنترل ها خودشون میدونند باید فرزندانشون Dispose بشن.
فرم خودش یک کنترل ئه، داخل Dispose کنترل هم Dispose طوری نوشته شده که فرزندان و نوه و نتیجه هاش هم Dispose بشن.
پس Designer برای اینکه کنترل های داخل فرم Dispose بشن نیازی به کد نوشتن اضافی نداره و بصورت پیشفرض و بدون کد نویسی اینکار انجام میشه و از بابت Dispose شدن کنترل های روی فرم نگرانی نداره.
اما برای کمپوننت ها اینطور نیست، اون کدی که اضافه میکنه برای کنترل ها نیست، برای کمپوننت ها است، مثل Timer و BackgroundWorker و ... که والد ندارن که روی فرم قرار بگیرند.
کنترل ها که روی فرم قرار می گیرند، ولی کمپوننت هایی مثل Timer که پنجره و ظاهر ندارند روی فرم قرار نمی گیرند، والد ندارند. برای همین موقع Dispose شدن فرم باید لیستی ازشون داشته باشیم که Dispose بشن.
اون لیست همون components ئه. جزئی از یک مجموعه IContainer میشوند که بعدا بشه موقع Dispose کردنش بهشون دسترسی داشت.
برای همین فرم به اون متغیر components نیاز داره که کمپوننت های فرم به مجموعه اضافه بشن تا موقع Dispose شدن فرم لیست کمپوننت ها موجود باشه تا Dispose بشن.

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

پس سر آخر ، وقتی اون اورلود متد Dispose (درون کلاس Form1.Designer.cs) ، چجوری میفهمه که کدوم کمپوننت ها و کنترل ها را باید dispose کنه؟
طبق روال Control.Dispose رفتار میکنه. کدش رو هم که می توانید پیدا کنید و ببینید. البته فرم خودش به این متد روال های دیگری اضافه میکنه، مثل آیکون و منو ... که باید نابود بشن.

و سر آخر ، چرا در Program.cs ، بعد از کد Application.Run ، اون فرم ای که نمایش داد را dispose نمیکنه؟
چون پنجره ای که به Application.Run تحویل داده میشه Dispose نشده که در نمیاد، با اجرای Application.Run ئه Dispose هم میشه.
میتوانید با یک متغیر جایگزین اش کنید تا ببینید اون متغیر بعد از Application.Run مقدار IsDisposed اش true هست یا نه.

اگه dispose کردن ، به همین سادگی هست ، پس چرا ما برای dispose کردن ، list ای از IDisposable درست کنیم و هر بار که شیِ جدیدِ قابلی dispose کردنی ای را میسازیم ، اون شی را به این لیست اضافه میکنیم؟ خوب ، ما هم این روش اش را بریم ها.
متوجه نشدم که چه روشی مد نظرتونه که میگید بهتره، ولی Container که داره شبیه همون لیستی که پیشنهاد کردم عمل می کنه. اگه منظورتون این باشه که لیست نباشه، باید برای هر شیء یک متغیر مجزا در نظر بگیرید که یکی یکی Dispose میخواد و با for قابل خلاصه کردن نیست. بجاش لیست باشه، هم کد نویسی کمتری میخواد و هم جمع و جور تره.

من همیشه متد dispose کردن را با آزاد کردنِ کل حافظه ی managed مربوط به اون شی ، قاتی میکردم . :) فکر میکردم وقتی dispose میکنیم ، کنترل مون ناپدید میشه ، پس شبیه به gc عمل میکنه و همه ی منابع را از حافظه پاک میکنه . واسه ی همین ، همیشه تعجب میکردم که اگه gc هست ، پس dispose واسه چی هست .
الان یه کم بیشتر متوجه شدم . دات نت برای کنترل هاشون و کلا کمپوننت هاشون ، در بخشی از کدهاشون ، از api ویندوز استفاده میکنند . api ویندوز هم از زبان ++C استفاده میکنند که میدونیم unmanaged هستند . وقتی dispose میکنیم ، این منابع api های ویندوز (که unmanaged هستند) را از حافظه پاک میکنند.
درسته دیگه؟
بله. درسته. البته در Dispose برنامه نویس هر کار دلخواهی رو انجام میده، ممکنه کلاسی اصلا منبع Unmanaged نداشته باشه ولی برنامه نویس برای نابود شدنش کار خاصی در نظر بگیره.
مثلا بعضی کلاس ها از (Dispose(true استفاده می کنند که فرضا متغیر های NET. شون که حافظه Managed دارند هم null بشن که در ادامه آزاد بشن ولی حالت کلی اینه که Dispose منابع Unmanaged رو آزاد کنه.
 

the_king

مدیرکل انجمن
سلامی مجدد
استاد ، این کمپوننت برای چیه؟ :

ImageGlue - Professional Dynamic Image Generation for the Web

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خیلی ممنون
استاد ، در متد OnPaint که در کلاس فرزند override کردیم ، لازمه خودمون بعد از رسم ، شی e.Graphics را dispose کنیم یا خودش انجام میده؟ دقت کنید که از درونش ، متد base.OnPaint(e) را فراخونی نکردیم .
اینو گفتم چون شما گفتین هر کی هر شی جدیدی را خلق کنه ، مسئولیست اش باهاش هست . چون شیِ e.Graphics در متد OnPaint را من ایجاد نکردم .
 

the_king

مدیرکل انجمن
خیلی ممنون
استاد ، در متد OnPaint که در کلاس فرزند override کردیم ، لازمه خودمون بعد از رسم ، شی e.Graphics را dispose کنیم یا خودش انجام میده؟ دقت کنید که از درونش ، متد base.OnPaint(e) را فراخونی نکردیم .
اینو گفتم چون شما گفتین هر کی هر شی جدیدی را خلق کنه ، مسئولیست اش باهاش هست . چون شیِ e.Graphics در متد OnPaint را من ایجاد نکردم .
نه. شیء ای که شما ایجاد کننده اش نیستید مسئولیت Dispose کردنش هم با شما نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
خیلی ممنون استاد
استاد ، دستور زیر را که از parallel استفاده کردم ، پروسه ی برنامه ام ، از تمام هسته های پردازنده ام استفاده کرد (پردازه ام بیشتر از 95 درصد ، در سربرگ process در Task Manager استفاده کرد) (پردازنده ام i5 4460 هه . 4 هسته ای هه) :

کد:
        int ParallelCounter = 0;
        private void Button6_Click(object sender, EventArgs e)
        {
            Action<int> action = new Action<int>(this.ActionHandler);
            System.Threading.Tasks.Parallel.For(0, 1000000000, action);
            this.button6.Text = this.ParallelCounter.ToString();
        }

        private void ActionHandler(int par)
        {
            this.ParallelCounter++;
        }

تعجبم از اینه که پس چرا وقتی در پست زیر ، از Parallel.Foreach استفاده کردم (برای جستجو در فایل ها و فولدرهای یک درایو) ، فقط از یک هسته تونست استفاده کنه! (25 درصد از توان پردازنده) . قضیه چیه؟! چرا این دو کد در استفاده از توان پردازنده ، فرق دارن؟ :

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

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

این کد را هم میزنم ، همین طور پردازنده را بیش از 85 درصد اشغال میکنه :

کد:
List<int> parallelForeachList = new List<int>();
        private void Page4_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 100000000; i++)
            {
                this.parallelForeachList.Add(i);

            }
           
        }

        private void Button7_Click(object sender, EventArgs e)
        {
            Action<int> action = new Action<int>(this.ActionForeachHandler);
            System.Threading.Tasks.Parallel.ForEach<int>(this.parallelForeachList, action);
            this.label1.Text = "";
        }

        private void ActionForeachHandler(int par)
        {
            this.ParallelCounter++;
        }
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام
خیلی ممنون استاد
استاد ، دستور زیر را که از parallel استفاده کردم ، پروسه ی برنامه ام ، از تمام هسته های پردازنده ام استفاده کرد (پردازه ام بیشتر از 95 درصد ، در سربرگ process در Task Manager استفاده کرد) (پردازنده ام i5 4460 هه . 4 هسته ای هه) :

کد:
        int ParallelCounter = 0;
        private void Button6_Click(object sender, EventArgs e)
        {
            Action<int> action = new Action<int>(this.ActionHandler);
            System.Threading.Tasks.Parallel.For(0, 1000000000, action);
            this.button6.Text = this.ParallelCounter.ToString();
        }

        private void ActionHandler(int par)
        {
            this.ParallelCounter++;
        }

تعجبم از اینه که پس چرا وقتی در پست زیر ، از Parallel.Foreach استفاده کردم (برای جستجو در فایل ها و فولدرهای یک درایو) ، فقط از یک هسته تونست استفاده کنه! (25 درصد از توان پردازنده) . قضیه چیه؟! چرا این دو کد در استفاده از توان پردازنده ، فرق دارن؟ :

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

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

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

SajjadKhati

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

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

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

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

the_king

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

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

کد شما داخل ماشین مجازی NET. اجرا میشه، نه پردازنده واقعی. شما که برای پردازنده واقعی کد نمی نویسید که صحبت هسته پردازنده بکنید. همونطور که شما وقتی با کلاس Graphics کار می کنید هیچ ارتباطی با کارت گرافیکی و درایورش ندارید. شما با Parallel میگید فلان روتین ها بصورت موازی انجام بشن، هسته پردازنده و ... مربوط به برنامه نویس نیست، ماشین مجازی NET. به شیوه خودش به تعدادی که لازمه نخ میسازه و عملیات رو بصورت موازی انجام میده، ممکنه از نخ هایی که ساخته چند بار و برای چندین عملیات استفاده مجدد بکنه. شما به عنوان برنامه نویس #C از هر جور موارد سخت افزاری و مربوط به وظایف سیستم عامل دور نگه داشته میشید. هسته پردازنده جزء منابع سیستم عامل ئه، در اختیار کد شما قرار نمیگیره که برایش نقشه میکشید. شما تلاش می کنید الگوریتمی بسازید که بتونه به روتین هایی تقسیم بشه که با اجرا بصورت موازی بلکه سریعتر به نتیجه برسه و بعد با Parallel امتحان می کنید که ببینید در واقعیت هم اجرای موازی به سربارش میارزه یا نه، شاید اصلا موازی اجراش کردید بدتر کند شد. اصلا غیر عادی و عجیب نیست که برخی الگوریتم ها قابل تقسیم بندی و موازی اجرا شدنی نیستند، یا موازی شدنشون اونقدر سربار داره که بجای سریعتر شدن کندتر میشن. و اینکه NET. برای اجرای روتین های موازی شما چند تا نخ میسازه یا به چند هسته نیاز داره به خودش مربوطه، کد شما که برای Parallel مشخص می کنید، باید موازی اجرا بشه که میشه، چطور میشه و با چند نخ و در چند هسته میشه رو چیکار دارید. برنامه شما یگانه برنامه موجود در سیستم عامل نیست، سایر برنامه هم باید نوبت اجرا داشته باشند، شما که نباید بجای سیستم عامل تصمیم بگیرید که چه هسته هایی رو درگیر کنه.

شما در زبان های سطح بالا مثل #C با قابلیت های انتزاعی و ساده ای سر و کار دارید که NET. در داخل ماشین مجازی ارائه می کنه. Parallel با ماشین مجازی NET. در ارتباط ئه، کارکردش هم ساده است، یکسری عملیات رو بصورت موازی اجرا میکنه. چند تا هسته و چند تا نخ و ... ایناش مربوط به مدیریت ماشین مجازی و سیستم عامل ئه. شما و کدتون اصلا درگیر این چیزها نمیشید. شما برای هسته سیستم عامل برنامه نمی نویسید.
 

SajjadKhati

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

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

کد شما داخل ماشین مجازی NET. اجرا میشه، نه پردازنده واقعی. شما که برای پردازنده واقعی کد نمی نویسید که صحبت هسته پردازنده بکنید. همونطور که شما وقتی با کلاس Graphics کار می کنید هیچ ارتباطی با کارت گرافیکی و درایورش ندارید. شما با Parallel میگید فلان روتین ها بصورت موازی انجام بشن، هسته پردازنده و ... مربوط به برنامه نویس نیست، ماشین مجازی NET. به شیوه خودش به تعدادی که لازمه نخ میسازه و عملیات رو بصورت موازی انجام میده، ممکنه از نخ هایی که ساخته چند بار و برای چندین عملیات استفاده مجدد بکنه. شما به عنوان برنامه نویس #C از هر جور موارد سخت افزاری و مربوط به وظایف سیستم عامل دور نگه داشته میشید. هسته پردازنده جزء منابع سیستم عامل ئه، در اختیار کد شما قرار نمیگیره که برایش نقشه میکشید. شما تلاش می کنید الگوریتمی بسازید که بتونه به روتین هایی تقسیم بشه که با اجرا بصورت موازی بلکه سریعتر به نتیجه برسه و بعد با Parallel امتحان می کنید که ببینید در واقعیت هم اجرای موازی به سربارش میارزه یا نه، شاید اصلا موازی اجراش کردید بدتر کند شد. اصلا غیر عادی و عجیب نیست که برخی الگوریتم ها قابل تقسیم بندی و موازی اجرا شدنی نیستند، یا موازی شدنشون اونقدر سربار داره که بجای سریعتر شدن کندتر میشن. و اینکه NET. برای اجرای روتین های موازی شما چند تا نخ میسازه یا به چند هسته نیاز داره به خودش مربوطه، کد شما که برای Parallel مشخص می کنید، باید موازی اجرا بشه که میشه، چطور میشه و با چند نخ و در چند هسته میشه رو چیکار دارید. برنامه شما یگانه برنامه موجود در سیستم عامل نیست، سایر برنامه هم باید نوبت اجرا داشته باشند، شما که نباید بجای سیستم عامل تصمیم بگیرید که چه هسته هایی رو درگیر کنه.

شما در زبان های سطح بالا مثل #C با قابلیت های انتزاعی و ساده ای سر و کار دارید که NET. در داخل ماشین مجازی ارائه می کنه. Parallel با ماشین مجازی NET. در ارتباط ئه، کارکردش هم ساده است، یکسری عملیات رو بصورت موازی اجرا میکنه. چند تا هسته و چند تا نخ و ... ایناش مربوط به مدیریت ماشین مجازی و سیستم عامل ئه. شما و کدتون اصلا درگیر این چیزها نمیشید. شما برای هسته سیستم عامل برنامه نمی نویسید.

خیلی ممنون استاد از توضیح مفصل تون :rose:
منظورم از استفاده ی چند هسته ، این نیست که الگوریتم بهینه نباشه یا برای استفاده از چند هسته ، سربار زیادی ایجاد کنیم . این قضایا رو میدونم . منظورم این هه که حالا که الگوریتم ها را بهینه کردیم و کارهای مستقل ای داریم که هم نیاز به پردازنده داره و هم نیازی به ارتباط بین دستورها نداره ، و سربار زیادی هم برای دو نخ مون ایجاد نمیکنه ، حالا چجوری میشه دو نخ را در دو هسته ی متفاوت اجرا کرد .

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

بعد اینکه الان نرم افزارهایی که از سی شارپ استفاده میکنن و سنگین هم هستن مثل یونیتی ، اینها باید بتونن گزینه ای در اختیار برنامه نویس بذارن که نخ ای که میسازه را بتونه در هسته های مختلف اجرا کنه دیگه . درسته؟ چون بازی ها (مخصوصا اگه پیشرفته باشن که بازی های پیشرفته را هم در یونیتی میسازن) ، نیاز به این داره که برنامه نویس ، نخ ای که میسازه را بتونه در هسته ی دیگه اجرا کنه (چون الان بازی ها یک هسته خیلی کم شونه و تقریبا بازی ای دیده نمیشه که زیر 2 هسته را استفاده کنه . الان بازی ها تا 4 یا بیشتر هسته ها را استفاده میکنن) .
خوب اگه این حرفم درسته ، و یونیتی باید راهکار و کلاس ای ارائه بده که برنامه نویس بتونه نخ هاش را توی هسته ی مجزا اجرا کنه ، پس ویژال استودیو در دات نت فریم وورک برای این قضیه چی کار کرد؟ اگه که درست نیست ، پس بازی سازها چی کار میکنن که نخ هاشون را در دو هسته ی متفاوت اجرا میکنن؟
 

the_king

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

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

من یه تحقیقی کردم ، بجای استفاده از نخ های متفاوتی که در هسته های متفاوت اجرا بشه و بجای کلاس Thread از کلاس ThreadPool پیشنهاد استفاده دادن (به من پیشنهاد ندادن . توی متون انگلیسی تحقیق کردم ، کسی که همچین مبحثی را مطالبه میکرد ، کسان دیگه به اون طرف بجای استفاده از کلاس Thread ، کلاس ThreadPool را پیشنهاد دادن که البته گفتن هیچ ربطی نداره که در دو هسته ی متفاوت اجرا بشه ولی با این حال نمیدونم چرا برای اون سئوال طرف ، همچین پیشنهادی که ربطی نداره را جواب دادن)
من کلاس ThreadPool رو دیدم معناش را متوجه شدم ولی مفهوم شو متوجه نشدم برای چیه؟ کلا تفاوت این کلاس با کلاس Thread در کجاست و چه زمانی از ThreadPool (بجای کلاس Thread) استفاده میکنن؟
[/QUOTE]
فرض کنید که تعداد زیادی عملیات دارید که می توانند همزمان اجرا بشن، ولی همه شون کوچک هستند و زود تمام می شوند. می توانید برای دونه دونه این عملیات ها نخ بسازید ولی هدر دادن بیخودی منابع ئه. ThreadPool میتونه عملیات ها رو با یکسری نخ به تعداد محدود مدیریت کنه، یعنی تا سر یک نخ خلوت شد بهش عملیات دیگری بسپاره که باید اجرا بشه. این یعنی با تعداد کمی نخ همون کاری رو انجام بده که شما با نخ های زیاد و استفاده غیر بهینه انجام میدید.

بعد اینکه الان نرم افزارهایی که از سی شارپ استفاده میکنن و سنگین هم هستن مثل یونیتی ، اینها باید بتونن گزینه ای در اختیار برنامه نویس بذارن که نخ ای که میسازه را بتونه در هسته های مختلف اجرا کنه دیگه . درسته؟ چون بازی ها (مخصوصا اگه پیشرفته باشن که بازی های پیشرفته را هم در یونیتی میسازن) ، نیاز به این داره که برنامه نویس ، نخ ای که میسازه را بتونه در هسته ی دیگه اجرا کنه (چون الان بازی ها یک هسته خیلی کم شونه و تقریبا بازی ای دیده نمیشه که زیر 2 هسته را استفاده کنه . الان بازی ها تا 4 یا بیشتر هسته ها را استفاده میکنن) .
خوب اگه این حرفم درسته ، و یونیتی باید راهکار و کلاس ای ارائه بده که برنامه نویس بتونه نخ هاش را توی هسته ی مجزا اجرا کنه ، پس ویژال استودیو در دات نت فریم وورک برای این قضیه چی کار کرد؟ اگه که درست نیست ، پس بازی سازها چی کار میکنن که نخ هاشون را در دو هسته ی متفاوت اجرا میکنن؟
اولا برنامه شما نیست که باید در چند هسته اجرا بشه، برنامه شما صرفا باید نخ هایی بسازه که موازی بتوانند اجرا شوند، فقط همین. کاری که Parallel داره میکنه. ثانیا سنگینی پردازش بازی کامپیوتری در بخش پردازش گرافیکی و اندکی صوتی اونه که اونم Unity باید انجام بده، اصولا بخش مربوط به کد شما سنگین نیست. Unity ئه که باید درخواست برنامه شما رو با نخ های موازی اجرا کنه. اینکه Unity کار رو با چند نخ میکنه که مستقل از نخ برنامه شما است، دلیلی نداره نخ درخواست کننده برنامه شما چند هسته ای بشه.
 

SajjadKhati

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


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

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

خیلی ممنون استاد :rose:

اولا برنامه شما نیست که باید در چند هسته اجرا بشه، برنامه شما صرفا باید نخ هایی بسازه که موازی بتوانند اجرا شوند، فقط همین. کاری که Parallel داره میکنه. ثانیا سنگینی پردازش بازی کامپیوتری در بخش پردازش گرافیکی و اندکی صوتی اونه که اونم Unity باید انجام بده، اصولا بخش مربوط به کد شما سنگین نیست. Unity ئه که باید درخواست برنامه شما رو با نخ های موازی اجرا کنه. اینکه Unity کار رو با چند نخ میکنه که مستقل از نخ برنامه شما است، دلیلی نداره نخ درخواست کننده برنامه شما چند هسته ای بشه.

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

the_king

مدیرکل انجمن
خیلی ممنون استاد :rose:



خیلی ممنون استاد :rose:



خیلی ممنون استاد
خوب منم همین حرف شما را که قرمز کردم پرسیدم دیگه .
همینی که در پست قبل پرسیدم و هنوز به جوابش نرسیدم . اینکه چطور میشه (بجز کلاس Parallel) ، نخ ای ساخت که بتونن بصورت موازی اجرا بشن یا به عبارتی چطور در دات نت و سی شارپ ، کاری شبیه به کلاس Parallel کنیم؟
اگه نشدنی هه ، چطور یونیتی و همچنین کلاس Parallel این کار را میکنن و اگه شدنی هه ، چجوری هه؟
شما در هیچ حالتی از محدودیت های ماشین مجازی یا امکانات Framework ئه NET. در اختیار #C قرار داده فراتر نمی روید.
قبل از NET. 4 همین امکانات فعلی Parallel هم نبود. شاید در آینده امکانات بیشتری اضافه بشه. شما با نخ ساختن اجرای همزمان رو دارید، ولی چون مربوط به یک پروسه هستند طبعا اجراشون محدود به یک هسته است.
البته خیلی بعیده که بخواهید کاری برای اجرای موازی داشته باشید که Parallel پاسخگو نیاز تون نباشه. در ضمن خیلی به ندرت کاری در NET. انجام می دهید که واقعا به پردازش چند هسته ای نیاز باشه، بیشتر اوقات صرفا باید الگوریتم بهتری طراحی کنید. اگر برنامه ای نوشتید که در حالت عادی کند ئه ایراد از الگوریتم بد اونه، نه اجرای تک هسته ای بودنش.

#C یک زبان سطح بالا است و در حال حاضر با ماشین مجازی. زبانی که هم سطح بالا است و هم ماشین مجازی داره، یا مفسری ئه معمولا سرعت اجرا جزو ملاک های اصلی طراحی اش نبوده. #C از اون زبان هایی نیست که برای پردازشهای سنگین استفاده میشن چون اجرای کد های ماشین مجازی سربار داره. از نظر کارایی زبان هایی که کامپایلر Native دارند، مثل ++C/C مناسب اینجور موارد هستند، نه #C و Java و Visual Basic و Python و ...
در نظر بگیرید که #C ذاتا برای سخت افزار مشخصی طراحی نشده که به معماری پردازنده مشخصی ربطش بدیم، ممکنه ماشین مجازی روی پردازنده تک هسته ای اجرا بشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
آها خیلی ممنون استاد
پس ممکنه در آینده در دات نت این قابلیت اضافه بشه .
-----------------------------------
استاد ، استریم ها ، برای کار با منابع (منبع فایل ، حافظه ی رم ، شبکه و ...) هستند . درسته؟
اگه درسته ، تفاوت کلاس File (که باهاش میشه با فایل ها کار کرد و اطلاعات فایل ها را خوند و نوشت) ، با کلاس FileStream پس چیه؟
بعد وقتی اشاره گرها و کدهای unsafe در سی شارپ هستند یا تا زمانی که کلاس های Marshall هستند که میشه با اشاره گر اطلاعات را توی حافظه خوند و نوشت ، پس چه نیازی به MemoryStream هست؟ آیا همه شون یک کار را انجام میدن و فرقی نداره که از کدوم کلاس و از کدوم روش استفاده کنیم؟
اگه نه ، تفاوت شون چیه؟
 

the_king

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

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

بعد وقتی اشاره گرها و کدهای unsafe در سی شارپ هستند یا تا زمانی که کلاس های Marshall هستند که میشه با اشاره گر اطلاعات را توی حافظه خوند و نوشت ، پس چه نیازی به MemoryStream هست؟ آیا همه شون یک کار را انجام میدن و فرقی نداره که از کدوم کلاس و از کدوم روش استفاده کنیم؟
اگه نه ، تفاوت شون چیه؟
شباهتی به هم ندارند.
اشاره گر و کد های unsafe که برای تعریف اشاره گر و دسترسی مستقیم به حافظه Managed داخل زبان ئه.
و Marshal هم که برای ارتباط بین محیط Managed و Unmanaged و مدیریت منابع Unmanaged ئه.
MemoryStream هم که برای خواندن یا تولید داده های داخل حافظه Managed ای است که بصورت تدریجی تولید میشن.
این سه تا کارکردشون کاملا مجزا است، با هیچکدوم نمی توانید کار دیگری رو انجام بدید.
 

Arnika Goli

New Member
سلام دارم با سی شارپ یه ورد پد مینویسم.
در رویداد form closing نوشتم که اگه برنامه سیو نشده یه message box نشون بده با 3تا دکمه yes no cancel
بعد نوشتم که اگه yes انتخاب شد save dialog باز شه
اگه no انتخاب شد برنامه بسته بشه
حالا برای cancel چی باید بنویسم که برنامه بسته نشه؟
لطفن کمکم کنید ممنون
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام دارم با سی شارپ یه ورد پد مینویسم.
در رویداد form closing نوشتم که اگه برنامه سیو نشده یه message box نشون بده با 3تا دکمه yes no cancel
بعد نوشتم که اگه yes انتخاب شد save dialog باز شه
اگه no انتخاب شد برنامه بسته بشه
حالا برای cancel چی باید بنویسم که برنامه بسته نشه؟
لطفن کمکم کنید ممنون

سلام
برای دکمه ی Cancel ، کد :

کد:
e.Cancel = true;

را بنویسید.
 

the_king

مدیرکل انجمن
سلام دارم با سی شارپ یه ورد پد مینویسم.
در رویداد form closing نوشتم که اگه برنامه سیو نشده یه message box نشون بده با 3تا دکمه yes no cancel
بعد نوشتم که اگه yes انتخاب شد save dialog باز شه
اگه no انتخاب شد برنامه بسته بشه
حالا برای cancel چی باید بنویسم که برنامه بسته نشه؟
لطفن کمکم کنید ممنون
داخل همون FormClosing یک پارامتر e هست که یک e.Cancel داره که اگه به e.Cancel مقدار true بدید فرم بسته نمیشه.
اصولا یک متغیر خواهید داشت که مشخص کنه چیزی تغییر کرده که موقع بستن فرم نیاز به Save کردن باشه یا نه :
کد:
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_changed == false)
            {
                return;
            }
            var result = MessageBox.Show(this, "Message", "Save", MessageBoxButtons.YesNoCancel);
            switch (result)
            {
                case DialogResult.Yes:
                    switch (saveFileDialog1.ShowDialog(this))
                    {
                        case DialogResult.OK:
                            // Save Code...
                            break;
                        case DialogResult.Cancel:
                            e.Cancel = true;
                            break;
                    }
                    break;
                case DialogResult.Cancel:
                    e.Cancel = true;
                    break;
            }
        }
 

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

بالا