PDA

View Full Version : حرفه ای: ایجاد نخ یا ورکرهای تودرتو



رامین مرادی
سه شنبه 22 آبان 1397, 14:30 عصر
سلام دوستان عزیز من یه برنامه ای دارم میسازم به دلیل اینکه با چند تا از ورودی ها داره کار میکنه و هنگ میکنه اومدم از بکگراند ورکر استفاده کردم. حالا من باید داخل این ورکر یه ورکر دیگه رو فراخونی کنم تا یه سری چیز های دیگه رو هم اجراکنه . نحوه پیاده سازیش موندم. در صورت امکان ممنون میشم راهنماییم کنید. ممنون. البته الان کد رو نوشتم و خروجی میگیرم. فقط مشکلی که پیش میاد وقتی ورکر2 رو اجرا میکنم برنامه هنگ میکنه و بعد از اتمام دستورات خروجی صادره میشه یه جا. ولی بدون ورکر دو قسمت ورکر یک کامل بدون هنگی اجرا میشه.


//start main code
{
//Run Worker1
}




//worker1 method
{
for (int i = 0; i < 254; i++)
{
//my code
if (Result == "OK")
{
//Run Worker2(Arguman->Result)
}
}
}


//worker2 method
{
//my code
//Result+=this method result
}
//Worker1 Complate method
{
Consol.WriteLine("Result");
}



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

Mahmoud.Afrad
سه شنبه 22 آبان 1397, 14:48 عصر
اینطور نمیشه نظر داد. کد کامل بگذارید.

رامین مرادی
سه شنبه 22 آبان 1397, 15:30 عصر
اینطور نمیشه نظر داد. کد کامل بگذارید.

این کد رو ببینید الان این کد پوشه ای به تعداد ورودی ایجاد میکنه و در داخل هر پوشه صد پوشه جدید درست میکنه.



private void button1_Click(object sender, EventArgs e)
{
int i=int.Parse(textBox1.Text);
progressBar1.Maximum = i-1;
progressBar2.Maximum = 99;
backgroundWorker1.RunWorkerAsync(i);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int i = int.Parse(textBox1.Text);
for (int j = 0; j < i; j++)
{
Directory.CreateDirectory("D:\\TestWork"+j.ToString());
backgroundWorker2.RunWorkerAsync(j);
backgroundWorker1.ReportProgress(j);
}
}


private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}


private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.Value = 0;

}


private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
int j=int.Parse(e.Argument.ToString());
for (int i = 0; i < 100; i++)
{
Directory.CreateDirectory("D:\\TestWork" + j.ToString()+""+i.ToString());
backgroundWorker2.ReportProgress(i);
}

}


private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar2.Value = e.ProgressPercentage;
}


private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar2.Value = 0;
}



حالا این دوتا تداخل ایجاد میکنن. و کار دومی تموم نشده اولی دوباره دومی رو دوباره فراخوانی میکنه که خطای مشغول بودن میده.

mr.sirwan
سه شنبه 22 آبان 1397, 17:49 عصر
سلام
خب توی این کد شما دقیقا چه لزومی به استفاده از ورکر دوم هست؟ کار ورکر دوم رو داخل حلقه ورکر اول هم میشه انجام داد کدتون خواناتر و تمیزتر هم میشه و دیگه نیازی به این همه ایونت نخواهد بود. اما دلیلتون چیه که از دوتا ورکر استفاده میکنین؟ (مگه اینکه کار اصلی ای که میخواین انجام بدین به سادگی ایجاد کردن پوشه نباشه) :متفکر:

رامین مرادی
چهارشنبه 23 آبان 1397, 08:15 صبح
سلام
خب توی این کد شما دقیقا چه لزومی به استفاده از ورکر دوم هست؟ کار ورکر دوم رو داخل حلقه ورکر اول هم میشه انجام داد کدتون خواناتر و تمیزتر هم میشه و دیگه نیازی به این همه ایونت نخواهد بود. اما دلیلتون چیه که از دوتا ورکر استفاده میکنین؟ (مگه اینکه کار اصلی ای که میخواین انجام بدین به سادگی ایجاد کردن پوشه نباشه) :متفکر:

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

Mahmoud.Afrad
چهارشنبه 23 آبان 1397, 09:12 صبح
به احتمال قریب به یقین به دفعات UI را درگیر میکنید و یا فاصله تغییر در UI کم هست به همین دلیل رابط کاربری هنگ میکند.

رامین مرادی
چهارشنبه 23 آبان 1397, 09:30 صبح
به احتمال قریب به یقین به دفعات UI را درگیر میکنید و یا فاصله تغییر در UI کم هست به همین دلیل رابط کاربری هنگ میکند.
UI رو بله یکی دوبار داخل ورکر یک فراخوانی میکنم. حالا ممنون میشم اگه راه حلی دارید برا این مورد بگید. از اینکه نمیتونم سورس اصلی رو اینجا بزارم پوزش میطلبم:ناراحت:
ورکر یک یک حلقه ای رو آغاز میکنه
فعالیتشو انجام میده
مقدار بدست اومده رو به ورکر دو پاس میده
ورکر دو حلقه ای رو اجرا میکنه و نتیجه رو داخل یه متغییر ذخیره میکنه
ورکر یک نتیجه خودش و نتیجه موجود تو متغییر رو میخونه و در دیتاگرید ثبت میکنه.و میره گام دیگه ای از حلقه رو اجرا کنه.

این کل فعالیتیه که انجام میشه. اگه راه حل دیگه ای دارید ممنون میشم راهنماییم کنید. فقط مسئله اصلی اینه برنامه هنگ نکنه(جلوی سایر فعالیت هارو بگیره مشکلی نیست اما نباید هنگ بکنه)

Mahmoud.Afrad
چهارشنبه 23 آبان 1397, 10:56 صبح
متد ReportProgress رو داخل حلقه ها فراخوانی میکنید؟ تعداد تکرار حلقه ها چندتاست؟
اگر ورکر1 صبر میکنه تا ورکر2 کارش تمام بشه این یعنی نیازی به ورکر2 نیست و بایست کدها در ورکر1 ادغام بشوند.

رامین مرادی
چهارشنبه 23 آبان 1397, 14:18 عصر
متد ReportProgress رو داخل حلقه ها فراخوانی میکنید؟ تعداد تکرار حلقه ها چندتاست؟
اگر ورکر1 صبر میکنه تا ورکر2 کارش تمام بشه این یعنی نیازی به ورکر2 نیست و بایست کدها در ورکر1 ادغام بشوند.
آره داخل حلقه فراخوانی میکنم.
تعداد حلقه ورکر یک از 1 تا 254 میتونه باشه.
حلقه ورکر دو میتونه از 1 تا مثلا 6000 تا هم باشه.
وقتی میارم داخل حلقه یک متسفانه بعد از انجام همه به یکباره خروجی میده.نه اینکه مرحله به مرحله.

Mahmoud.Afrad
چهارشنبه 23 آبان 1397, 17:05 عصر
آره داخل حلقه فراخوانی میکنم.
تعداد حلقه ورکر یک از 1 تا 254 میتونه باشه.
حلقه ورکر دو میتونه از 1 تا مثلا 6000 تا هم باشه.
وقتی میارم داخل حلقه یک متسفانه بعد از انجام همه به یکباره خروجی میده.نه اینکه مرحله به مرحله.

مقدار ماکزیمم progressBar ها را بذارید 100 باشه.
یک متغیر به عنوان «درصد پیشرفت قبلی» نیاز دارید تا درصد پیشرفت جدید را با اون مقایسه کنید.
قبل از فراخوانی متد ReportProgress درصد پیشرفت را محاسبه کنید. مثلا اگر تعداد نهایتا 6000 باشه کافیه شمارنده حلقه را تقسیم بر 6000 بعد حاصل رو ضرب در 100 کنید . نتیجه را با «درصد پیشرفت قبلی» مقایسه کنید، اگر متفاوت بود به عنوان پارامتر به ReportProgress ارسال کنید.
با این کار فقط زمانی UI درگیر میشه که درصد پیشرفت تغییر کند.