PDA

View Full Version : سوال: مشكل فريز شدن فرم، در حين اجراي يك Thread



newgoldenman
سه شنبه 24 دی 1387, 18:38 عصر
سلام به همه ي دوستان
من يه فرم دارم، توي اون دو تا دكمه دارم!! يكي دكمه ي Search و ديگري Stop !
Search رو كه ميزنم، توي مسيري مشخص، توي فايلها، شروع به جستجو ميكنه. ولي يه مشكلي هست:
وقتي كه متد جستجو، با زدن اين دكمه شروع به كار ميكنه، بقيه ي فرم، فريز ميشه و نميه با اجزاي اون كار كرد.

براي رفع مشكلم، از Theard استفاده كردم. بدين ترتيب كه يك Thread با زدن دكمه ي Search ، شروع ميكنم و همه چيز خوب پيش ميره! يعني متد جستجو توي يك Thread ديگه كارش رو انجام ميده.

ولي با اين حال، هنوز هم مشكل فريز شدن فرمم حل نشده و نميتونم دكمه ي Stop رو براي Abort كردن Thread بزنم.

در ضمن، براي دسترسي به اشياء فرم، درون اون Threadكه متد جستجو داخلش شروع به كار ميكنه، از delegate نيز استفاده كردم و مشكلي با كنترل اشياي فرم درون Thread جستجو ندارم.

من دقيقاً اينو ميخوام بدونم كه:
چيكار كنم كه وقتي يك Thread داره اجرا ميشه، كاربر هنوز هم بتونه با اشياء ديگر فرم كار كنه و فرمم فريز نشه.

پيشاپيش از راهنمايي و توجه همه ي دوستان عزيزم تشكر و قدرداني ميكنم.

Sajjad.Aghapour
سه شنبه 24 دی 1387, 18:55 عصر
خوب خاصیت Thread هم همینه.کار شما رو تو یه شاخه و یه نخ دیگه انجام میده.یعنی قاعدتا فرم شما باید تحت اختیار خودتون باشه........

newgoldenman
سه شنبه 24 دی 1387, 19:26 عصر
انگار شما تا آخر سوال منو نخوندي دوست خوبم.
مشكل من اينه كه فرمم تحت كنترل خودم نيست.

Sajjad.Aghapour
سه شنبه 24 دی 1387, 22:02 عصر
می تونید کدتون رو بذارید ؟

newgoldenman
سه شنبه 24 دی 1387, 22:43 عصر
بله با كمال ميل:



public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public Thread oThread;
private void buttonStart_Click(object sender, EventArgs e)
{
oThread = new Thread(new ThreadStart(SearchInFiles));
oThread.Start();
}
delegate void myDelegate();
public void SearchInFiles()
{
if (listBox4.InvokeRequired)
{
myDelegate del = new myDelegate(SearchInFiles );
Invoke(del);
}
else
{
//My Search Codes Body Goes Here


}
}
private void buttonStop_Click(object sender, EventArgs e)
{
oThread.Abort();
}
}


از شما و نيز مابقي دوستان، كه وقت ميزارن و كد منو بررسي ميكنن، سپاسگزارم.

once4ever
چهارشنبه 25 دی 1387, 09:29 صبح
نکته اول اینه که خاصیت اجرا شدن ترد در پشت زمینه رو ست نکردید

oThread.IsBackground = true;

و نکته دوم اینه که تو این موارد بهتره از BackgroundWorker استفاده کنید هم راحتتره و هم مطمئن تر

Sajjad.Aghapour
چهارشنبه 25 دی 1387, 12:34 عصر
نمی دونم مشکلتون رفع شد یا نه.ولی فکر می کنم اگه از Async استفاده کنید راحت ترید(همون BGWorker که دوستمون گفتن) یا اینکه داخل متد سرچتون delegate تون رو invoke کنید.......

Sajjad.Aghapour
چهارشنبه 25 دی 1387, 14:43 عصر
ببخشید مثال یادم رفت(ویرایش نکردم چون گفتم شاید نبینید)....
دو کد زیر رو امتحان کنید و تفاوتش رو ببینید...


private void button1_Click(object sender, EventArgs e)
{
t = new Thread(new ThreadStart(temp));
t.Start();
}

private void temp()
{
myDel del = new myDel(main);
for (int i = 0; i < 10; i++)
{
this.Invoke(del);
Thread.Sleep(1000);
}
}

private void main()
{
listBox1.Items.Add("sa");
}



private void button2_Click(object sender, EventArgs e)
{
t = new Thread(new ThreadStart(tmp));
t.Start();
}
private void tmp()
{
if (listBox2.InvokeRequired)
{
myDel del = new myDel(tmp);
this.Invoke(del);
}
else
{
for (int i = 0; i < 10; i++)
{
listBox2.Items.Add("sa");
Thread.Sleep(1000);
}
}
}

newgoldenman
چهارشنبه 25 دی 1387, 14:45 عصر
once4ever جان، ممنونم بابت توجهت به سوال من. من اون كاري كه فرمودين انجام دادم، ولي باز همچنان فرمم فريز ميشه و اگه بخوام دكمه اي چيزي در حين جستجو بزنم، Not Responding ميشه فرمم!!
اون BackgroundWorker هم كه فرمودين، تاحالا كار نكردم خدايي! اگه لطف كنيد يه توضيحاتي يا لينكي مفيد معرفي كنيد، خيلي خيلي ممنون ميشم.

sajjadlove عزيز،
داخل متد سرچتم delegate رو invoke کردم.
ولي نميدونم چرا هنوز مشكل دارم.
در مورد BackgroundWorker هم چيزي نميدونم. ميتوني شما كمكم كني؟

اين تاپيك رو پيدا كردم (http://barnamenevis.org/forum/showthread.php?t=108704&highlight=BackgroundWorker) كه يكسري آموزش داده، ولي VB.Net هست. مهم نيست، تبديل ميكنم! مهم يادگرفتنه. شما يك نگاهي بندازيد، ببينيد اين لينك مفيد هست كه بخونمش يا خير!

باز هم ممنونم از شما. اگر بتونيد توي همين نمونه كدي كه خودم نوشتم، مشكلاتمو گوشزد كنيد، بسيار سپاسگذار ميشم. يا اينكه BackgroundWorker كه ميفرماييد رو توي همين مثال من پياده سازي كنيد.
بسيار ممنونم. موفق باشيد.

Amir Oveisi
چهارشنبه 25 دی 1387, 15:33 عصر
else
{
//My Search Codes Body Goes Here


}


اینجا چیز بخصوصی نوشتین؟؟

Sajjad.Aghapour
چهارشنبه 25 دی 1387, 15:39 عصر
در مورد BGWorker که داخل همین تاپیک هم میتونید مطلب پیدا کنید......
اما در مورد مشکل شما:
کد اولی که برات گذاشتم مشکلت رو رفع میکنه.شما باید متد سرچ رو داخل temp بنویسید.اگر در مسیر مشخص چیزی پیدا کرد که اونوقت باید delegate رو invoke کنید........


private void temp()
{
myDel del = new myDel(main);
{
search code
if(found)
this.Invoke(del);
}
}

newgoldenman
چهارشنبه 25 دی 1387, 17:32 عصر
اینجا چیز بخصوصی نوشتین؟؟
بله. دقيقاً ايناهاش!:لبخندساده:
اينجا، از توي listBox2 يكي يكي رشته هاي حاوي فايلهايي كه قبلاً توي listBox2 Add شده اند، برداشته، فايل مورد نظر رو ميخونه، اگر رشته ي textBox2.Text توي اون فايل بود، رشته ي فايل مورد نظر رو به listBox4 اضافه ميكنه.


else
{
///////////////////////////
//Begin To This Function !!
///////////////////////////
textBox1.Clear();
listBox4.Items.Clear();
if (!radioButton3.Checked && listBox2.Items.Count != 0)
{
for (int i = 0; i < listBox2.Items.Count; i++)
{
StreamReader myReader = new StreamReader(listBox2.Items[i].ToString());
string myStr = myReader.ReadToEnd().ToLower();
if (myStr.Contains(textBox2.Text))
{
listBox4.Items.Add(listBox2.Items[i].ToString());
}
progressBar1.PerformStep();
}
}
}

newgoldenman
چهارشنبه 25 دی 1387, 17:34 عصر
در مورد BGWorker که داخل همین تاپیک هم میتونید مطلب پیدا کنید......
اما در مورد مشکل شما:
کد اولی که برات گذاشتم مشکلت رو رفع میکنه.شما باید متد سرچ رو داخل temp بنویسید.اگر در مسیر مشخص چیزی پیدا کرد که اونوقت باید delegate رو invoke کنید........


private void temp()
{
myDel del = new myDel(main);
{
search code
if(found)
this.Invoke(del);
}
}


نميشه سجاد جان:افسرده: توي انجمن هم جستجو كردم يكمي، چيز مفيدي نيافتم!

Sajjad.Aghapour
چهارشنبه 25 دی 1387, 18:11 عصر
گفتم که همون کد اول کارت رو راه میندازه.حالا نمی دونم راه بهتری در استفاده از Thread ها به این صورت هست.(البته کد زیر استاندارد نیست)


int count;
private void button1_Click(object sender, EventArgs e)
{
count = listBox1.Items.Count;
t = new Thread(new ThreadStart(temp));
t.Start();
}
bool b;
object obj;
private void temp()
{
myDel del = new myDel(main);
for (int i = 0; i < count; i++)
{
b = result(listBox1.Items[i].ToString());
if (b)
{
obj = listBox1.Items[i];
this.Invoke(del);
Thread.Sleep(2000);
}
}
}
private bool result(string file)
{
StreamReader r = new StreamReader("c:\\" + file + ".txt");
string s = r.ReadToEnd();
if (s.Contains("sajjad"))
return true;
return false;

}
private void main()
{
listBox2.Items.Add(obj);
}

Mahdi.Kiani
چهارشنبه 25 دی 1387, 21:27 عصر
سلام
توصیه می کنم که به جای کار کردن با Thread ها به صورت مستقیم، از Delegate ها و متدهای Invoke آن ( Begin و end ) استفاده کنی.
علاوه بر این پیشنهاد می کنم کنم که Update کردن کنترل های UI را با عملیات اصلیتون درگیر نکنید. اهمیت این موضوع زمانی بیشتر می شود که در عمل اصلیتون نتایج زیادی داشته باشید و بخواهید آن نتایج را به کنترل های Ui بفرستید. اگر مدت زمان کافی برای Update شدن کنترل UI مورد نظر وجود نداشته باشد، فرمتون Freez می شود.

newgoldenman
پنج شنبه 26 دی 1387, 05:59 صبح
با تشكر فراوان از دوست عزيزم bermooda ي گل، بايد خدمت ايشون و نيز شما عزيزان عرض كنم كه، مشكل بنده با به نخ كشيدن توابع جستجوم حل شد.
چون من 3تا تابع داشتم، و هر كدوم هم توي يك ريسمان جداگانه احظار ميشد، مشكلم اين بود كه تا ريسمان اول كارش تموم نشده، نبايد ريسمان دوم شروع بشه و بهمين ترتيب ريسمان سوم. چرا كه اطلاعاتي كه هر ريسمان جمع آوري ميكنه، منبع اطلاعات براي ريسمان بعدي هست.
براي رفع اين مشكل، از دو تا تايمر استفاده كردم. كه توي تايمر اول بعنوان مثال، مدام چك كردم كه اگر ريسمان اول به پايان رسيده، دومي رو شروع كن و ...

به هر حال، از همگي دوستان عزيزم، بالاخص bermooda ي عزيز و جوانمرد، كه در به جواب رسيدن اين مشكل من كمك كردند و وقت گذاشتند، بسيار سپاسگذارم.