PDA

View Full Version : خارج شدن از حلقه



delasaee
دوشنبه 11 مرداد 1389, 19:14 عصر
سلام
من یه برنامه دارم که یه حلقه رو با زدن یک دکمه شروع می کنه که شاید چند دقیقه طول بکشه تا تموم بشه
حالا شاید کاربر وسط کار بیخیال شد خواست کنسل کنه
من یه دکمه گذاشتمن واسه توقف که با زدنش یه متغیر 1 میشه و داخل حلقه چک میکنم که اگه اون متغیر مساوی 1 شد از حلقه خارج شو

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

Saman_12
دوشنبه 11 مرداد 1389, 19:19 عصر
حلقه ی شما داخل کدوم رویداد شی هست اسم شی رو هم ذکر کنید ؟

nasim bahari
دوشنبه 11 مرداد 1389, 19:24 عصر
سلام........

راه درست اینه که شما شمارنده حلقه رو درون حلقه تغییر ندین........

راه حل :

شما از یه متغییر بولین ( این متغییر Public باشه ) استفاده کنید که با زدن دکمه Stop یا Cancel مقدار اون False بشه و در درون حلقه این متغییر رو چک کنین که اگر برابر False بود از حلقه با استفاده از دستور زیر خارج بشه.....


Exit For

موفق باشین

Saman_12
دوشنبه 11 مرداد 1389, 19:31 عصر
ببین نسیم خانوم روشی که گفتین کار بردی هست اما اگه حلقه به تو مثال داخل فورم لود باشه تا تموم شدن حلقه امکان خارج شدن از اون نیست.:لبخند:.

delasaee
دوشنبه 11 مرداد 1389, 19:31 عصر
حلقه ی شما داخل کدوم رویداد شی هست اسم شی رو هم ذکر کنید ؟

من از کامپوننت dotnetbar استفاده می کنه
حلقه تو رویداد buttonitem کلیک هست





سلام........

راه درست اینه که شما شمارنده حلقه رو درون حلقه تغییر ندین........

راه حل :

شما از یه متغییر بولین ( این متغییر Public باشه ) استفاده کنید که با زدن دکمه Stop یا Cancel مقدار اون False بشه و در درون حلقه این متغییر رو چک کنین که اگر برابر False بود از حلقه با استفاده از دستور زیر خارج بشه.....


Exit Forموفق باشین


منم همین کارو کردم
ولی قضیه اینه که اصلاً برنامه هنگ میکنه نمیتونم دکمه توقف رو کلیک کنم

Saman_12
دوشنبه 11 مرداد 1389, 19:49 عصر
بهتره از حلقتون توی یک تایمر استفاده کنید توی حلقه تون هم چک کنید که آیا متغییر مقدار True داره یا نه و آخر تایمر هم Enabled تایمر رو False کنید. وتوی اون باتون که قراره حلقه رو استوپ کنه مقدار متغییر را True قرار دهید .(البته بعید میدونم درست شه چون وقتی فورم هنگ میکنه دیگه ....)

Saman_12
دوشنبه 11 مرداد 1389, 20:37 عصر
یافتم یافتم .جواب رو یافتم!!!
اصلا تایمر و متغییر رو فرا موش کن!:خجالت:
اگه می خواین توی حلقه های طولانی برنامه هنگ نکنه اولین چیزی که توی حلقه تون می نویسین باید کد زیر باشه :

Application.DoEvents()
زحمتش مال جناب Mani_rf هست.

FastCode
دوشنبه 11 مرداد 1389, 20:46 عصر
کد:
Application.DoEvents()

زود پاکش کن تا بچه کار درست ها حالتو نگرفتن.

روش بهتر اینه که از یه backgroundworker استفاده کنید.یا اینکه بگید چه پردازشی داره انجام میشه.

Saman_12
دوشنبه 11 مرداد 1389, 21:33 عصر
ببین دوست عزیز من خودم این کد رو چند وقت پیش توی یه تایپک توی همین سایت دیدم.(یادم نبود که از اون تایپیک یه فایل Html ذخیره کرده ام.زحمت این کد رو هم جاب Mani_rf کشیده بودن و مطلبش هم مرتبط با حلقه های طولانی بود که با عث هنگ کردن فورم میشه.بعید میدونم ای شون تازه کار باشن؟!):متعجب:
درمورد BakgrounWorker هم یه توضیح میدادین بد نبود!بود؟؟

mohammad.moosaei
دوشنبه 11 مرداد 1389, 22:30 عصر
ببین دوست عزیز من خودم این کد رو چند وقت پیش توی یه تایپک توی همین سایت دیدم.(یادم نبود که از اون تایپیک یه فایل Html ذخیره کرده ام.زحمت این کد رو هم جاب Mani_rf کشیده بودن و مطلبش هم مرتبط با حلقه های طولانی بود که با عث هنگ کردن فورم میشه.بعید میدونم ای شون تازه کار باشن؟!):متعجب:
درمورد BakgrounWorker هم یه توضیح میدادین بد نبود!بود؟؟


بهترین کار اینه که از یک بند پردازش جدا استفاده کنی تا کاری به بقیه پروسس ها نداشته باشه :


راه حل من برای مشکل شما اینه که فکر کنم بهترین راه حل باشه و منطقی هم هست :

این کد کارتون رو راه میندازه و به هیچ وجهه برنامتون گیر نمی کنه و میتونید همزمان چند کا رو با هم انجام بدید :




Private threadMain As System.Threading.Thread

Private Sub yourSub()

While (True)

'your Code...

End While

End Sub

Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click

Me.threadMain = New System.Threading.Thread(AddressOf yourSub)
Me.threadMain.Start()

End Sub

Private Sub CancelButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelButton.Click

Me.threadMain.Abort()

End Sub

delasaee
دوشنبه 11 مرداد 1389, 22:35 عصر
یافتم یافتم .جواب رو یافتم!!!
اصلا تایمر و متغییر رو فرا موش کن!:خجالت:
اگه می خواین توی حلقه های طولانی برنامه هنگ نکنه اولین چیزی که توی حلقه تون می نویسین باید کد زیر باشه :

Application.DoEvents()زحمتش مال جناب Mani_rf هست.

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

delasaee
دوشنبه 11 مرداد 1389, 22:54 عصر
بهترین کار اینه که از یک بند پردازش جدا استفاده کنی تا کاری به بقیه پروسس ها نداشته باشه :


راه حل من برای مشکل شما اینه که فکر کنم بهترین راه حل باشه و منطقی هم هست :

این کد کارتون رو راه میندازه و به هیچ وجهه برنامتون گیر نمی کنه و میتونید همزمان چند کا رو با هم انجام بدید :




Private threadMain As System.Threading.Thread

Private Sub yourSub()

While (True)

'your Code...

End While

End Sub

Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click

Me.threadMain = New System.Threading.Thread(AddressOf yourSub)
Me.threadMain.Start()

End Sub

Private Sub CancelButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelButton.Click

Me.threadMain.Abort()

End Sub



آقا دستت درد نکنه معلومه این کد همونه که من می خوام
فقط من دارم از کامپوننت image xpress استفاده می کنم که این ارور رو میده وقتی از thread استفاده می کنم

یه سوال دیگه این خط end sub نداره؟

Private threadMain As System.Threading.Thread

Saman_12
دوشنبه 11 مرداد 1389, 23:26 عصر
از mohammad.moosaei خیلی متشکرم راه حل جالبی ارائه دادند از کد شون استفاده بردیم.:قلب:

یه سوال دیگه این خط end sub نداره؟

Private threadMain As System.Threading.Thread
تو اونجایی که من میدونم این یک Sub نیست که بخواد End Sub داشته باشه کاربرد کلمه Private توی این کد مثل کلمه Dim هستش(اگه باور ندارید می تونید جای Private از کلمه Dim استفاده کنید):لبخند:

delasaee
دوشنبه 11 مرداد 1389, 23:32 عصر
برای اون ارور راه حلی ندارید؟

mahdi1373
دوشنبه 11 مرداد 1389, 23:54 عصر
زود پاکش کن تا بچه کار درست ها حالتو نگرفتن.

روش بهتر اینه که از یه backgroundworker استفاده کنید.یا اینکه بگید چه پردازشی داره انجام میشه.

من با این کد کار می کنم، تا حالا هم هیچ مشکلی نداشتم. به نظرم خیی هم خوب کار می کنه. اگه ممکنه دلیل مخالفتتون رو بگین.

delasaee
سه شنبه 12 مرداد 1389, 00:37 صبح
پس از ساعت ها جستجو بالاخره یافتم راه حل اون ارورو



Control.CheckForIllegalCrossThreadCalls = False
Me.threadMain2 = New System.Threading.Thread(AddressOf yourSub)
Me.threadMain2.Start()
Control.CheckForIllegalCrossThreadCalls = False
این یه خط رو اضافه کردم ولی اصلاً نمیدونم چیکار می کنه
ولی برنامه داره خیلی خوب کار میکنه انگار نه انگار داره یه حلقه طولانی پردازش میشه
جالب اینه که بعد از توقف دوباره شروع رو میزنم ادامه حلقه رو ادامه می ده

FastCode
سه شنبه 12 مرداد 1389, 07:04 صبح
برای جلوگیری از خطا باید از Control.Invoke استفاده کنید.

VB.NET 2010
سه شنبه 12 مرداد 1389, 18:36 عصر
فکر کنم اینطوری خیلی ساده و راحت باشه
یه متغیر public بولین تعریف کن و قبل از شروع حلقه true باشه و توی حلقه از doevents استفاده کن و بررسی کن اگه متغیر false شد از حلقه خارج بشه exit for
یه کامند واسه false کردن هم بذار

محسن شامحمدی
سه شنبه 12 مرداد 1389, 18:44 عصر
برای جلوگیری از خطا باید از Control.Invoke استفاده کنید.

توی این سورس به طور کامل این کار آموزش داده شده

Saman_12
سه شنبه 12 مرداد 1389, 18:47 عصر
من این کد رو امتحان کردم ولی همچنان هنگ می کنه :لبخند:
پردازشی که تو حلقه انجام میشه تصاویر رو از تو یه فولدر می خونه و گزینه هایی که تو عکس تیک خورده رو بر می گردونه
دوست عزیز VB.NET 2010 مثل اینکه شما پست بالا رو نخوندین!

delasaee
چهارشنبه 13 مرداد 1389, 01:21 صبح
دوست عزیز VB.NET 2010 مثل اینکه شما پست بالا رو نخوندین!

متوجه نمیشم؟
یعنی اون کدی که دادید فقط تو 2010 کار میکنه؟
من ندیدم جایی گفته باشید 2010

Saman_12
چهارشنبه 13 مرداد 1389, 09:32 صبح
نه اشتباه نکنید من با کاربر VB.net 2010 بودم!

mahdi1373
چهارشنبه 13 مرداد 1389, 13:17 عصر
من فکر می کنم اشکال شما با

Application.DoEvents()

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

mohammad.moosaei
پنج شنبه 14 مرداد 1389, 16:52 عصر
آقا دستت درد نکنه معلومه این کد همونه که من می خوام
فقط من دارم از کامپوننت image xpress استفاده می کنم که این ارور رو میده وقتی از thread استفاده می کنم

یه سوال دیگه این خط end sub نداره؟

Private threadMain As System.Threading.Thread

سلام دوباره و ببخشید اگه دیر شد اخه Net در دسترسم نبود :

دوست عزیز اگه شما توی تابعی که توسط Thread اجرا میشه بخواهید به خاصیتهای کنترلهای دیگه مقدار بدید مثلا image یک PicBox رو عوض کنید باید اونو توی یک delegate فراخوانی کنید :

مثلا من توی مثال زیر اعداد رو توی یک TextBox نشون میدم و برای اضافه کردن اعداد توی TextBox باید یک Delegate بنویسم چون دارم خاصیت یک کنترل رو تغییر میدم که خودش از یک Thread جدا استفاده میکنه :




Private threadMain As System.Threading.Thread

Private Delegate Sub Add_Safe(ByVal value As String)

Private Sub Add(ByVal value As String)

TextBox1.Text = value

End Sub

Private Sub ShowNumbers()

For i As Integer = 0 To 1000000

Dim dlgate As New Add_Safe(AddressOf Add)
Me.Invoke(dlgate, i.ToString)

System.Threading.Thread.Sleep(500)

Next

End Sub


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Me.threadMain = New System.Threading.Thread(AddressOf ShowNumbers)
threadMain.Start()

End Sub




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

اگر هم مشکلی بود کد رو بزارید تا درستش کنم .


راستی اون خطی رو هم که گفتی end sub نداره من فقط یک نتغیر از نوع thread تعریف کردم .


یا علی

delasaee
یک شنبه 17 مرداد 1389, 19:26 عصر
سلام دوباره و ببخشید اگه دیر شد اخه Net در دسترسم نبود :

دوست عزیز اگه شما توی تابعی که توسط Thread اجرا میشه بخواهید به خاصیتهای کنترلهای دیگه مقدار بدید مثلا image یک PicBox رو عوض کنید باید اونو توی یک delegate فراخوانی کنید :

مثلا من توی مثال زیر اعداد رو توی یک TextBox نشون میدم و برای اضافه کردن اعداد توی TextBox باید یک Delegate بنویسم چون دارم خاصیت یک کنترل رو تغییر میدم که خودش از یک Thread جدا استفاده میکنه :




Private threadMain As System.Threading.Thread

Private Delegate Sub Add_Safe(ByVal value As String)

Private Sub Add(ByVal value As String)

TextBox1.Text = value

End Sub

Private Sub ShowNumbers()

For i As Integer = 0 To 1000000

Dim dlgate As New Add_Safe(AddressOf Add)
Me.Invoke(dlgate, i.ToString)

System.Threading.Thread.Sleep(500)

Next

End Sub


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Me.threadMain = New System.Threading.Thread(AddressOf ShowNumbers)
threadMain.Start()

End Sub




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

اگر هم مشکلی بود کد رو بزارید تا درستش کنم .


راستی اون خطی رو هم که گفتی end sub نداره من فقط یک نتغیر از نوع thread تعریف کردم .


یا علی

ممنون دوست عزیز
من مجبور شدن 6 تا delegateتعریف کنم و مشکلم حل شده
ولی سرعت پردازش حلقه تقریباً 1/3 شده و حلقه کند کار می کنه
این مشکل برای چی هست؟

FastCode
یک شنبه 17 مرداد 1389, 20:08 عصر
فکر کنم اینطوری خیلی ساده و راحت باشه
یه متغیر public بولین تعریف کن و قبل از شروع حلقه true باشه و توی حلقه از doevents استفاده کن و بررسی کن اگه متغیر false شد از حلقه خارج بشه exit for
یه کامند واسه false کردن هم بذار
به جای این کار میتونه ازThread.Join یا یک عدد waithandle استفاده کنه.

پس از ساعت ها جستجو بالاخره یافتم راه حل اون ارورو



Control.CheckForIllegalCrossThreadCalls = False
Me.threadMain2 = New System.Threading.Thread(AddressOf yourSub)
Me.threadMain2.Start()
Control.CheckForIllegalCrossThreadCalls = False
این یه خط رو اضافه کردم ولی اصلاً نمیدونم چیکار می کنه
ولی برنامه داره خیلی خوب کار میکنه انگار نه انگار داره یه حلقه طولانی پردازش میشه
جالب اینه که بعد از توقف دوباره شروع رو میزنم ادامه حلقه رو ادامه می ده
این کار غلطه.بهتره از همون Control.Invoke استفاده کنید.

من با این کد کار می کنم، تا حالا هم هیچ مشکلی نداشتم. به نظرم خیی هم خوب کار می کنه. اگه ممکنه دلیل مخالفتتون رو بگین.
what is the Problem with Application.DoEventsتوی گوگل سرچ کن:


ممنون دوست عزیز
من مجبور شدن 6 تا delegateتعریف کنم و مشکلم حل شده
ولی سرعت پردازش حلقه تقریباً 1/3 شده و حلقه کند کار می کنه
این مشکل برای چی هست؟
شما میتونید اون Sleepرو حذف کنید یا این که با یه ترد دیگه Image ها رو توی یه Circular Buffer که برای همین کار ابداع شده بریزید و از سرعت بیشتر از قبل لذت ببرید.

delasaee
یک شنبه 17 مرداد 1389, 20:30 عصر
شما میتونید اون Sleepرو حذف کنید یا این که با یه ترد دیگه Image ها رو توی یه Circular Buffer که برای همین کار ابداع شده بریزید و از سرعت بیشتر از قبل لذت ببرید.


ممنون دوست عزیز مشکلم با حذف sleep حل شد

کار sleep چی هست؟

FastCode
یک شنبه 17 مرداد 1389, 20:48 عصر
ممنون دوست عزیز مشکلم با حذف sleep حل شد

کار sleep چی هست؟
sleep یعنی این:
http://en.wikipedia.org/wiki/Sleep:قهقهه::قهقهه::قهقهه:
شما به برنامه گفته بودی که بین هر عمل نیم ثانیه صبر کن.

delasaee
یک شنبه 17 مرداد 1389, 21:10 عصر
sleep یعنی این:
http://en.wikipedia.org/wiki/Sleep:قهقهه::قهقهه::قهقهه: (http://en.wikipedia.org/wiki/Sleep:%D9%82%D9%87%D9%82%D9%87%D9%87::%D9%82%D9%87 %D9%82%D9%87%D9%87::%D9%82%D9%87%D9%82%D9%87%D9%87 :)
شما به برنامه گفته بودی که بین هر عمل نیم ثانیه صبر کن.

خب اون دوستمون که این کد رو گذاشته برای چی این کارو کرده
آیا لازمه بین هر عمل مقداری صبر کرد یا هیچ فرقی نمی کنه؟

mohammad.moosaei
یک شنبه 17 مرداد 1389, 21:19 عصر
ممنون دوست عزیز
من مجبور شدن 6 تا delegateتعریف کنم و مشکلم حل شده
ولی سرعت پردازش حلقه تقریباً 1/3 شده و ‎
حلقه کند کار می کنه
این مشکل برای چی هست؟

سلام :‎
دوست من قسمت thread.sleep
رو پاک کن . این برای تنظیم سرعت بر حسب ms هستش. اگه اینو برداری با آخرین سرعت کار میکنه و مشکلت حل میشه.

delasaee
جمعه 22 مرداد 1389, 21:28 عصر
ممنون از تمام دوستان که به نحوی کمک کردن به من
برنامه من الان داره به درستی کار می کنه
ولی بعضی وقتا که حلقه زیاد باید تکرار بشه وسط کار استوپ میشه
یا کلاً هنگ می کنه
بعد دوباره برنامه رو اجرا می کنم درست کار میکنه
بدون استفاده از مولتی ترد این مشکلو نداشتم ولی دکمه استوپ کار نمی کرد
ولی الان همه چی درسته ولی بعضی وقتا هنگ می کنه
میترسم موقع تحویل برنامه این اتفاق بیوفته ضایع بشم

مشکل از کجای کارمه بنظر شما؟

FastCode
جمعه 22 مرداد 1389, 23:51 عصر
از Control.Invoke استفاده کردید یا پشت گوش انداختید.
احتمال میدم برای همین باشه.

delasaee
شنبه 23 مرداد 1389, 17:39 عصر
از Control.Invoke استفاده کردید یا پشت گوش انداختید.
احتمال میدم برای همین باشه.

من از delegate استفاده کردم

امکان داره یکم بیشتر توضیح بدید چطوری از control.invoke استفاده کنم

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