PDA

View Full Version : سوال: مشکلات مالتی ترد در پاس دادن پارامتر



s3rv3r
یک شنبه 20 مرداد 1392, 16:17 عصر
سلام دوستان من یه فانکشن نوشتم

private void Get_Data_Thread(int id,int lendata)
{
add_deligage_textbox(lendata);
}


فراخوانی با ترد هم به صورت زیر هستش

for(int dbid=0;dbid<40;dbid++)
Thread thwork = new Thread(delegate()
{
Get_Data_Thread(dbid, lendbgeted);
});
thwork.start();
Thread.sleep(500);
}


حالا وقتی وقتی اجرا میکنم انتظار دارم که اعداد 1 تا 40 به ترتیب به تکست باک اضافه بشن
ولی این اتفاق نمیفته 40 بار داده به تکست باکس اضافه میشه ولی تکراری داخلش هست به این صورت مثلا و حالا تصادفی عوض میشه اعداد

انگار که داده قبلی رو پاس میده.

1
2
3
4
5
6
7
7
9
10
11
12
12
13
.
.
.

ممنون میشم یکی کمکم کنه

lavymini
یک شنبه 20 مرداد 1392, 16:38 عصر
سلام از حلقه موازی استفاده کن

int[] a=new int[40];
Parallel.For(0, a.Length, (int i) =>
}
textbox1.text += a[i];
});

s3rv3r
یک شنبه 20 مرداد 1392, 16:42 عصر
ممنون دوست عزیز.

میشه بگی چطوری به فانکشن که نوشتم پاس بدم؟

چون حالا صرفا اضافه کردن به تکست باکس نیست کارم.

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

lavymini
یک شنبه 20 مرداد 1392, 16:51 عصر
میشه یه کاملتر بنویسی که من کپی کنم VS تست کنم آخه اینا کپی میکنم خطا میده

s3rv3r
دوشنبه 21 مرداد 1392, 17:54 عصر
ببینید یه مشکلی که هست تو مولتی ترد کردن

اینه که داده های یه فانکشن که ربطی به جاهای دیگه نداره موقع مالتی ترد کردن کار نتیجه نادرست میده . یا به نظر میاد کار مقایسه و اینارو انجام نمیده ترد. نمیدونم واقعا

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


public void Get_Data_Thread(int rownumberin)
{
string word = "";
int low = 32;
int hight = 127;
int mid = 0;
int searchchar = (int)mytext[rownumberin];
while (low < hight)
{
mid = (int)((low + hight) / 2);

if (searchchar > mid )
{
low = mid + 1;
}
else
{
if (searchchar == mid)
{
arrayfind[rownumberin] = Convert.ToChar(mid) + "";
word = Convert.ToChar(mid) + "";
break;
}
else
{
hight = mid;
}
}

}
add_txt_log("Column: " + rownumberin + " CHar-> " + Convert.ToChar(mid));
Thread.Sleep(1000);
ThreadWork--;
}



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

ممنون میشم دوستان کمک کنند یا این نمونه رو تغییر بدن ببینیم مشکل از چیه

cpppro
دوشنبه 21 مرداد 1392, 19:47 عصر
سلام
فک کنم مشکل شما این بود که از یک ترد منفرد استفاده کرده بودین . درواقع باید از یه آرایه یا لیست یا .... برای تولید تردها به صورت مجزا استفاده کنین.

108981

s3rv3r
دوشنبه 21 مرداد 1392, 21:05 عصر
خیلی ممنونم دوست عزیز واقعا لطف کردی. تا حدود زیادی مشکل حل میشه

اگر در این قسمت ترد Sleep نشه بازم به همون مشکل میخوره. و اطلاعات نادرست به دست میاد. علت خاصی داره که داده ها بهم میریزن؟؟

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


private void start_job()
{
int lentext = mytext.Length;
arrayfind = new string[lentext+1];
int lendbgeted = 0;
while (lentext > lendbgeted || ThreadWork != 0)
{
if (ThreadWork < ThreadMax && lentext > lendbgeted)
{
ThreadWork++;
add_lable(lendbgeted + " " + string.Join("", arrayfind));
thwork[ThreadWork] = new Thread(() => Get_Data_Thread(lendbgeted)); //********
thwork[ThreadWork].IsBackground = true;
thwork[ThreadWork].Start();
lendbgeted++;
}
Thread.Sleep(100);
}
}

Mahmoud.Afrad
دوشنبه 21 مرداد 1392, 22:48 عصر
شما به تعداد تکرار حلقه داری ترد ایجاد میکنی در صورتی که باید یک ترد ایجاد کنی و حلقه رو داخل متدی بنویسی که به ترد پاس میدی.
مثال:

private void button2_Click(object sender, EventArgs e)
{
Thread t = new Thread(MyMethod) {IsBackground = true};
t.Start();
}

private void MyMethod()
{
UpdateDelegate myDel = new UpdateDelegate(UpdateTxt);

for (int i = 0; i < 40; i++)
{
this.Invoke(myDel, i);
}
}

private delegate void UpdateDelegate(int a);
private void UpdateTxt(int a)
{
textBox1.Text += a + ",";
}

مهرداد صفا
دوشنبه 21 مرداد 1392, 23:52 عصر
سلام دوستان من یه فانکشن نوشتم

private void Get_Data_Thread(int id,int lendata)
{
add_deligage_textbox(lendata);
}


فراخوانی با ترد هم به صورت زیر هستش

for(int dbid=0;dbid<40;dbid++)
Thread thwork = new Thread(delegate()
{
Get_Data_Thread(dbid, lendbgeted);
});
thwork.start();
Thread.sleep(500);
}


حالا وقتی وقتی اجرا میکنم انتظار دارم که اعداد 1 تا 40 به ترتیب به تکست باک اضافه بشن
ولی این اتفاق نمیفته 40 بار داده به تکست باکس اضافه میشه ولی تکراری داخلش هست به این صورت مثلا و حالا تصادفی عوض میشه اعداد

انگار که داده قبلی رو پاس میده.

1
2
3
4
5
6
7
7
9
10
11
12
12
13
.
.
.

ممنون میشم یکی کمکم کنه

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

//in the name of god
//صل الله علی محمد و آله

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
////////////test1
Console.WriteLine("test1");
for (int i = 0; i < 40; i++)
{
Thread thread2 = new Thread(delegate()
{

Console.WriteLine(i);
});
thread2.Start();

}
Thread.Sleep(100);
Console.WriteLine(new string('-',80));
//////////////test2
Console.WriteLine("test2");
for (int j = 0; j < 40; j++)
{
Thread thread3 = new Thread(() => Console.WriteLine(j));
thread3.Start();
}
Thread.Sleep(100);

Console.WriteLine(new string('-',80));
/////////////test3
Console.WriteLine("test3");
List<Thread> threads = new List<Thread>();
for (int i = 0; i < 40; i++)
{
threads.Add(new Thread(() => Console.WriteLine(i)));

}
threads.ForEach((thread4) => thread4.Start());
Console.WriteLine(new string('-', 80));
//////////////test4
Console.WriteLine("test4");
threads.Clear();
for (int j = 0; j < 40; j++)
{
Thread thread5=new Thread((ParameterizedThreadStart)Console.WriteLine );
thread5.Start(j);
}
Console.WriteLine(new string('-',80));
//////////////test5
for(int i=0;i<40;i++)
{
Thread thread6=new Thread((ParameterizedThreadStart)Console.WriteLine );
thread6.Start(i);
Thread.Sleep(25);

}
}
}
}


نتیجه:


test1
0
1
2
3
4
6
6
8
8
10
10
12
12
14
14
16
16
18
18
20
20
22
22
24
24
26
26
28
28
30
30
31
32
33
34
36
36
38
38
39
--------------------------------------------------------------------------------

test2
1
1
2
4
3
6
6
8
10
9
12
7
11
13
14
15
16
17
18
19
21
20
22
23
24
25
27
27
28
29
30
31
32
34
35
36
36
38
38
40
--------------------------------------------------------------------------------

test3
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
40
--------------------------------------------------------------------------------

test4
0
1
2
3
4
5
6
7
8
9
10
12
11
13
15
14
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
32
31
33
34
35
36
37
39
38
--------------------------------------------------------------------------------

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Press any key to continue . . .


مثالهای test1 و test2 که در واقع دقیقا یکی هستند و خروجی ممکن است نا مرتب و تکراری باشد.
در test3همانطور که می بینید چون threadها بعد از حلقه اجرا می شوند، در هر 40 thread عدد 40 (عددی که در زمان اجرای thread در i است و نه در زمان ساخت آن) نمایش داده می شود.
در test4 مقادیر متغیرها در زمان ساخت thread مورد استفاده قرار میگیرد ولی ممکن است یک thread زودتر از thread قبلی خود اجرا شود و اعداد کاملا به ترتیب نباشند که برای حل این موضوع بهتر است از یک thread برای همه موارد استفاده شود و یا اینکه بعد از اجرای هر htread به thread اصلی کمی استراحت داده شود تا thread قبلی کاملا شروعبه کار کند.