سوال در مورد Thread

bitaroos

Member
سلام دوستان

در مورد سوالایی که در زیر پرسیدم، هر اطلاعاتی چه کم چه زیاد، چه کامل چه ناقص دارید،
ممنون میشم راهنماییم کنید


یه سوال داشتم درباره ی Thread. من دقیقا نمی دونم چی جوری میتونم از Thread ها استفاده کنم.

به عنوان مثال توی فتوشاپ وقتی یه عملیات سنگین داره صورت میگیره (مثلا باز کردن یه فایل PSD حجیم)
، یه messageBox باز میشه که اجازه ی cancel کردن این فرایند رو به ما میده.

چطور میشه اینکارو کرد؟

و اینکه چه جور میشه پایان کار رو تخمین زد، مثلا موقع رایت cd، یا رندر گرفتن از یه پروژه (مثلا After effect)،
یه تخمین از اتمام کار میزنه و یه شمارش معکوس تا پایان انجام عملیات نشون میده.

آیا invoke هم مثل thread عمل میکنه؟ اگر فرقی دارن فرقشون چیه؟

با تشکر
 

the_king

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

در مورد سوالایی که در زیر پرسیدم، هر اطلاعاتی چه کم چه زیاد، چه کامل چه ناقص دارید،
ممنون میشم راهنماییم کنید


یه سوال داشتم درباره ی Thread. من دقیقا نمی دونم چی جوری میتونم از Thread ها استفاده کنم.

به عنوان مثال توی فتوشاپ وقتی یه عملیات سنگین داره صورت میگیره (مثلا باز کردن یه فایل PSD حجیم)
، یه messageBox باز میشه که اجازه ی cancel کردن این فرایند رو به ما میده.

چطور میشه اینکارو کرد؟

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

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

در برنامه هایی که چند Thread دارند، معمولا Thread اصلی فقط به درخواست های کاربر مثل کلیک کردن روی دکمه ها
رسیدگی می کنه و هر زمانی که لازمه عملیات وقت گیری مثل کپی کردن یک فایل حجیم انجام بشه، یک Thread
جدید می سازه و کل فرایند کپی کردن فایل رو به اون Thread محول می کنه. از اونجایی که Thread ها بصورت همزمان
و مستقل از هم انجام می شوند هر زمانی که Thread اصلی تمایل داشت می تونه Thread جانبی رو Pause یا به کلی
Terminate کنه تا اجرایش متوقف بشه. زمانی که کاربر روی دکمه Cancel کلیک کرد Thread اصلی بیکاره و فورا
به درخواست کاربر Thread جانبی رو متوقف می کنه. به همین دلیل برنامه هایی که Multi-Thread هستند هم
در پاسخگویی به کاربر سریعتر اند و هم از توانایی پردازنده های چند هسته ای استفاده بهتری می کنند.

و اینکه چه جور میشه پایان کار رو تخمین زد، مثلا موقع رایت cd، یا رندر گرفتن از یه پروژه (مثلا After effect)،
یه تخمین از اتمام کار میزنه و یه شمارش معکوس تا پایان انجام عملیات نشون میده.
مدت زمان لازم برای انجام بعضی از عملیات ها به کلی قابل پیشبینی کردن نیستند، چون نه تعداد تکرار حلقه شان
مشخص است و نه زمان لازم برای هر تکرار. مثلا اگر بخواهید تعداد فایل های exe در پوشه و زیر پوشه های
مسیر C:\Windows رو بشمارید معلوم نیست که سیستم عامل چه مدت زمانی شما را معطل می کند.
نه تعداد فایل ها در ابتدا مشخص است و نه زمان لازم برای پیدا کردن فایل exe بعدی. در اینگونه موارد معمولا باید به
نمایش یک انیمیشن یا تایمر مدت زمانی سپری شده اکتفا کنید.

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

آیا invoke هم مثل thread عمل میکنه؟ اگر فرقی دارن فرقشون چیه؟

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

Invoke کردن در اصل یکجور Call کردن یعنی فراخوانی کردن یک روتین است، با این تفاوت که در
فراخوانی عادی همان Thread ای که دستور فراخوانی را داده خودش هم اجرا کننده روتین است. اما زمانی که
روتین Invoke می شود، اجرای روتین به Thread ای واگذار می شود که مسئول اصلی آن روتین است.

فرضا دکمه ای که روی فرم قرار دارد توسط Thread اصلی فرم اداره می شود و در خارج از محیط آن Thread
قابل دسترسی نیست. اگر شما بخواهید با یک Thread دیگر رخداد کلیک آن دکمه را مدیریت کنید به دلیل عدم
دسترسی به دکمه به مشکل بر می خورید. در اینگونه موارد با Invoke کردن عملیات را به Thread اصلی فرم
واگذار می کنند که به دکمه دسترسی مورد نیاز را دارد. Invoke کردن همانند این است که از Thread فرم
درخواست کنید که لطفا کاری را برای شما انجام دهد که بجز خودش Thread دیگری مجاز به انجام اش نیست.
 

bitaroos

Member
ممنون

تئوری threat رو کاملا متوجه شدم ولی عملا نمی دونم چه جوری میشه ازش استفاده کرد.
میشه یه نمونه از این برنامه ها رو برام بنویسید.

مثلا یه برنامه داریم، بازدن دگمه Start یه حلقه بینهایت شروع به کار میکنه و یه دگمه stop داریم
که بازدن اون، برنامه از حلقه خارج بشه، اگر یه دگمه pause هم وجود داشته باشه عالی میشه

ممنون
 

the_king

مدیرکل انجمن
ممنون

تئوری threat رو کاملا متوجه شدم ولی عملا نمی دونم چه جوری میشه ازش استفاده کرد.
میشه یه نمونه از این برنامه ها رو برام بنویسید.

مثلا یه برنامه داریم، بازدن دگمه Start یه حلقه بینهایت شروع به کار میکنه و یه دگمه stop داریم
که بازدن اون، برنامه از حلقه خارج بشه، اگر یه دگمه pause هم وجود داشته باشه عالی میشه

ممنون

1) برای دسترسی ساده تر به Thread ابتدای کد قبل از تعریف کلاس فرم System.Threading رو using می کنیم.
کد:
using System.Threading;

2) یک تابع می سازیم که باید توسط Thread اجرا شود :
کد:
        void MyCode()
        {
.
.
.
        }

3) یک Thread می سازیم که تابع مان را اجرا کند :
کد:
            Thread t = new Thread(new ThreadStart(MyCode));
            t.Start();

3) اگر می خواهید متغیری در کلاس فرم وجود داشته باشد که هم خود Thread اصلی و هم Thread جدید مان
به آن دسترسی داشته باشد باید مراقب تداخل های ناشی از دسترسی همزمان به متغیر باشیم. ساده ترین
شیوه جلوگیری از دسترسی همزمان استفاده از lock است، lock روی یک شیء دسترسی انحصاری ایجاد می کند
و تا زمانی که کد های داخل بلوک lock اجرا می شوند هیچ Thread دیگری به شیء مورد نظر دسترسی نخواهد داشت.
اگر Thread دیگری سعی کند به آن شیء دسترسی داشته باشد منتظر خواهد ماند تا از بلوک lock خارج شویم.

کد:
        object var = 0;

        void MyCode1()
        {
            while (true)
            {
                lock (var)
                {
                    var = (int)var + 2;
                }
            }
        }

        void MyCode2()
        {
            while (true)
            {
                lock (var)
                {
                    var = (int)var - 1;
                }
            }
        }

4) بصورت کلی یک Thread جدید نباید با کنترل های روی فرم کاری داشته باشد، آنها توسط Thread اصلی
مدیریت می شوند.

5) می توانید چندین Thread بسازید که همه شان یک تابع یکسان را اجرا کنند.

کد:
            for (int i = 0; i < 10; i++)
            {
                Thread t = new Thread(new ThreadStart(MyCode));
                t.Start();
            }

6) فراموش نکنید که قبل از خروج از فرم اصلی برنامه بررسی لازم انجام شود تا اجرای همه Thread هایی که
ساخته اید خاتمه یابند و Thread ای در حال اجرا نماند.

کد:
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (t.IsAlive)
            {
                t.Abort();
            }
        }

StartStopPauseThread.zip
 

پیوست ها

  • StartStopPauseThread.zip
    40.6 کیلوبایت · بازدیدها: 21
آخرین ویرایش:

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

بالا