PDA

View Full Version : مبتدی: اجرای همزمان چند ترد



Sal_64
سه شنبه 16 دی 1393, 16:32 عصر
سلام
چندین تابع طراحی شده که باید همزمان اجرا شن
به این صورت تردها طراحی کردم اما همزمان انجام نمی شن و بصورت پشت سر هم اجرا میشن
لطفا کد ببینید

t_3 = newThread(anjam_3);
t_3.IsBackground = true;
t_3.Start();



t_3_2 = newThread(anjam_3_2);
t_3_2.IsBackground = true;
t_3_2.Start();



t_3_3 = newThread(anjam_3_3);
t_3_3.IsBackground = true;
t_3_3.Start();


تشکر

hamid_hr
سه شنبه 16 دی 1393, 16:43 عصر
اینها به صورت همزمان اجرا میشوند(البته از دید کاربر)
یک احتمال وجود دارد که توابع خیلی زود کارشون تموم میشن و شما احساس میکنید پشت سر هم اجرا میشوند

Sal_64
سه شنبه 16 دی 1393, 19:31 عصر
تشکر
هر تابع در تکست باکس های متفاوت اعدادی نمایش میده (شمارنده) و کاملا مشخص که به ترتیب انجام میشن
در توابع از تایمر استفاده شده

SabaSabouhi
چهارشنبه 17 دی 1393, 13:41 عصر
سلام
بدون دیدن کد، سخت می‌شه حدس زد که مشکل جیه. یکی از اتفاق‌هایی که باعث ‌می‌شه 3 تا Thead همزمان اجرا نشن این هست که
اولین ترد یک شیء رو قفل کنه و بقیه منتظرش بمونن. شاید هم مشکل از تابع نمایش خروجی باشه که درست نمایش نمی‌ده.
اما کدی که تو پست خودتون گذاشتین اشکالی نداره. جای دیگه باید دنبال مشکل گشت.

صبا صبوحی

Sal_64
چهارشنبه 17 دی 1393, 22:01 عصر
سلام
بدون دیدن کد، سخت می‌شه حدس زد که مشکل جیه. یکی از اتفاق‌هایی که باعث ‌می‌شه 3 تا Thead همزمان اجرا نشن این هست که
اولین ترد یک شیء رو قفل کنه و بقیه منتظرش بمونن. شاید هم مشکل از تابع نمایش خروجی باشه که درست نمایش نمی‌ده.
اما کدی که تو پست خودتون گذاشتین اشکالی نداره. جای دیگه باید دنبال مشکل گشت.

صبا صبوحی
سلام
هر تابع به شي مختص خودش دسترسي داره (اشيا مشترك نيست)
فقط موردي كه هست براي دسترسي به اشيا روي فرم از invoke‌استفاده كردم چون دفعات دسترسي در تابع مذكور زياد بود اكثر كدها داخل invoke‌ حتي دستور وقفه
براي همين گاها رفتارهاي متناقض ديده ميشه (در ترتيب اجرا سه تابع)!

Sal_64
جمعه 19 دی 1393, 14:28 عصر
با خروج دستور وقفه از تابع invoke‌مورد حل شد

اما مطلب ديگه اي پيش اومد
مي خوام برنامه تا پايان انجام موفقيت آميز اين سه ترد كار ديگه اي انجام نده يا اصطلاحا منتظر پايان اين تردها بماند
از 3 فلگ استفاده كردم كه در پايان توابع true مي شوند
اما اين دستور انجام نمي شود


//پس از اتمام مراحس سه وارد مرحله چهار شود و انها را نیز به صورت موازی انجام دهد
if (flag_3 == true && flag_3_2 == true && flag_3_3 == true)
{


t_4 = new Thread(anjam_movazi_marhale_4);
t_4.IsBackground = true;
t_4.Start();


t_4_2 = new Thread(anjam_movazi_marhale_4_2);
t_4_2.IsBackground = true;
t_4_2.Start();

}

if (flag_4 == true && flag_4_2 == true)
{


تشكر

SabaSabouhi
شنبه 20 دی 1393, 14:41 عصر
سلام
از EventWaitHandle استفاده کن. البته به ازای هر کدوم از Threadها یکی باید استفاده کنی.
تو برنامه اصلی برای هر سه Wait کن، و پیش از تموم شدن هر کدوم از Threadها Set کن.
البته راه‌های دیگه هم داره. مثلاً تو یه حلقه فعال بودن Threadها رو چک کنی که کلی cpu time می‌گیره.

صبا صبوحی

Sal_64
یک شنبه 21 دی 1393, 17:32 عصر
سلام
از EventWaitHandle استفاده کن. البته به ازای هر کدوم از Threadها یکی باید استفاده کنی.
تو برنامه اصلی برای هر سه Wait کن، و پیش از تموم شدن هر کدوم از Threadها Set کن.
البته راه‌های دیگه هم داره. مثلاً تو یه حلقه فعال بودن Threadها رو چک کنی که کلی cpu time می‌گیره.

صبا صبوحی

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

Afshin160
دوشنبه 22 دی 1393, 00:43 صبح
سلام .
در مورد مشکل اولتون یعنی عدم همزمانی تردها همان طور که خودتون گفتید به علت invoke و دسترسی به منبعی که باعث lock شدن می شود تردها همزمان اجرا نمیشودن .
و اما مشکل دوم یعنی انجام موفقیت آمیز 3 ترد ...؟!
مطلب اول در مورد موفقیت آمیز بودن : با این روشی که شما کد نوشتید پی بردن به موفقیت آمیز بودن کار سختیه بنظر میاد و بهتر وارد این بحث نشیم . ولی در مورد اینکه تا 3 ترد کارشان تمام نشده کار دیگری انجام نشود یه راه غیر اصولی هست و اون هم استفاده از دستور :

Lock
{
.
...
}


که اگر کدی را درون این کروشه قراردهید تا اتمام تمام دستورات آن از منبع قفل شده حمایت می کند .

به عنون مثال :

class Program
{
static void func1()
{
try
{
Console.WriteLine("enter th1");

for (int i = 1; i < 100; i++)
{
Thread.Sleep(100);
Console.WriteLine("th1" + "--->" + i);
}

}
Console.WriteLine("exit th1");
}

static void func2()
{
Console.WriteLine("enter th2");

for (int i = 1; i < 100; i++)
{
Thread.Sleep(100);
Console.WriteLine("th2"+"--->"+i);
}
Console.WriteLine("exit th2");

}

static void func3()
{
Console.WriteLine("enter th3");

for (int i = 1; i < 10; i++)
{
Thread.Sleep(100);
Console.WriteLine("th3" + "--->" + i);
}
Console.WriteLine("exit th3");

}
static readonly object _object = new object();
static void Main(string[] args)
{
Thread th1 = new Thread(new ThreadStart(func1));
Thread th2 = new Thread(new ThreadStart(func2));
lock (_object)
{
Console.WriteLine("enter main thread ");

th1.Start();


th2.Start();
Console.ReadKey();
}
Thread th3 = new Thread(new ThreadStart(func3));
th3.Start();
Console.ReadKey();


}
}



تا زمانی که ما دسترسی به کنسول را قفل کرده ایم فقط ترد 1 و ترد 2 انجام می شود و بعد از اتمام آن ترد 3 انجام می شود . البته الویت انجام ترد 1 و 2 را خودش برحسب ترد های آزاد در سیستم انجام میدهد .
موفق باشید .

Sal_64
دوشنبه 22 دی 1393, 09:48 صبح
سلام
واسه تفهیم بیشتر یه نمونه کد گذاشتم

مشگل اینجاست تا پایان کار ، دستورات منتظر خواهند ماند اما عمل رفرش لیبل ها نمایش داده نمی شود !!!!
دوستان لطف میکنن ببین
نظرشرون بدن
تشکر

SabaSabouhi
دوشنبه 22 دی 1393, 16:15 عصر
سلام
راستش نمی‌دونم چطوری تو چند خلاصه بگم که کافی باشه. مطمئن هستم که اگه جستجو کنی جواب‌های کاملی پیدا می‌کنی.
اما خلاصه اینه:
1. تو کد اصلی به ازای هر کدوم از Threadها یه متغیر از جنس EventWaitHandle رو new می‌کنی.
2. با ایجاد هر Thread متغیر متناظرش رو بهش بده و Thread رو Start کن.
3. تو همون کد اصلی پس از ایجاد و شروع کردن کلیه Threadها متد WaitOne رو برای تمام EventWaitHandle فراخوانی کن.
4. تو هر Thread در پایان کار برای EventWaitHandle مربوطه، متد Set رو فراخوانی کن.

این یک راه حل اصولی نیست، اما کار شما رو راه می‌اندازه.
صبا صبوحی

پانوشت: اگه وقتم اجازه بده شاید روش کار با Threadها رو با مثال بنویسم و بگذارم اینجا.

Sal_64
دوشنبه 22 دی 1393, 20:08 عصر
سلام
راستش نمی‌دونم چطوری تو چند خلاصه بگم که کافی باشه. مطمئن هستم که اگه جستجو کنی جواب‌های کاملی پیدا می‌کنی.
اما خلاصه اینه:
1. تو کد اصلی به ازای هر کدوم از Threadها یه متغیر از جنس EventWaitHandle رو new می‌کنی.
2. با ایجاد هر Thread متغیر متناظرش رو بهش بده و Thread رو Start کن.
3. تو همون کد اصلی پس از ایجاد و شروع کردن کلیه Threadها متد WaitOne رو برای تمام EventWaitHandle فراخوانی کن.
4. تو هر Thread در پایان کار برای EventWaitHandle مربوطه، متد Set رو فراخوانی کن.

این یک راه حل اصولی نیست، اما کار شما رو راه می‌اندازه.
صبا صبوحی

پانوشت: اگه وقتم اجازه بده شاید روش کار با Threadها رو با مثال بنویسم و بگذارم اینجا.

سلام
تشکر
بنده نمونه کدی نوشتم
بر پایه همین توضیحات شما که
اما مورد جدیدی به وجود آمده:افسرده:
لطفا نمونه کد پست قبل بینید
تشکر

Sal_64
چهارشنبه 24 دی 1393, 09:26 صبح
سلام
ممنون میشم اگه دوستان اون نمونه کد دانلود و اجرا کنن
و بگن چرا ویژوال استدیو نمی تونه متن داخل لیبل همزمان با اجرای ترد رفرش کنه !!!!!
تشکر

SabaSabouhi
چهارشنبه 24 دی 1393, 10:23 صبح
سلام
اشکال کار شما اینه که روند عادی برنامه رو با wait کردن فلج کردی.
تو یه فرم ویندوزی نباید مستقیماً wait کنی.
تو کد دکمه‌ی خودت بجای فراخوانی متد این کار رو بکن:


var thread = new Thread( anjam_movazi );
thread.Start();



مشکلت حل می‌شه. و خواهش می‌کنم سعی کن تو نام‌گذاری بجای PINGLISH از واژه‌های انگلیسی استفاده کنی.
در غیر این صورت فقط خودت مشتری کار خودت خواهی بود. شاید اولش کمی سخت باشه، اما ارزشش رو داره.

صبا صبوحی

Sal_64
چهارشنبه 24 دی 1393, 23:28 عصر
سلام
واسه وقتي كه گذاشتين يه دنيا ممنون

//
از اونجا كه اين يك پروژه كوچك دانشجويي بود و تمام سعي هم بر اين بود كه به كد نويسي مبتدي نزديك باشد از عبارت فينگليش استفاده شده بود