PDA

View Full Version : ایجاد وقفه در اجرای دستور for



bita_naz
جمعه 21 آبان 1389, 19:47 عصر
سلام دوستان

من یک حلقه for دارم و میخام در هر بار که برنامه وارد حلقه میشه چند ثانیه زمان بگذره .

چطور این کارو انجام بدم ؟ با تایمر امتحان کردم ولی نشد

ممنون

mahdi87_gh
جمعه 21 آبان 1389, 19:55 عصر
هدفتون رو از این کار توضیح بدین امکان داره راه حل بهتری وجود داشته باشه. میخواین کاربر در جالت watting قرار بگیره؟

codelover
جمعه 21 آبان 1389, 20:16 عصر
سلام دوستان

من یک حلقه for دارم و میخام در هر بار که برنامه وارد حلقه میشه چند ثانیه زمان بگذره .

چطور این کارو انجام بدم ؟ با تایمر امتحان کردم ولی نشد

ممنون

این چه کاریه اگه وقفه می خواهید c sharp خودش این قابلیت رو داره از کلاس thread
دیگه لازم نیست از for استفاده کنید

از این تکه کد برای وقفه استفاده کنید فقط باید زمان رو بر حسب میلی ثانیه بدید که در این جا برنامه 2 ثانیه میره تو حالت sleep


System.Threading.Thread.Sleep(2000);

kamran00f
جمعه 21 آبان 1389, 20:18 عصر
سلام دوستان

من یک حلقه for دارم و میخام در هر بار که برنامه وارد حلقه میشه چند ثانیه زمان بگذره .

چطور این کارو انجام بدم ؟ با تایمر امتحان کردم ولی نشد

ممنون

خود تایمر اینکارو میکنه و حتی به حقه احتیاجی نیست. یه تایمر بساز، interval رو هر چند ثانیه که میخوای ست کن و بعد timer1.start(); رو فراخوانی کن. (البته باید event رو هم نوشته باشی اصولا دیگه!) وقتی تایمر استارت ش دیگه بعد از هر چند ثنیه که ست کردی اون event اجرا میشه. حالا برای اینکه بعد از تعداد مشخصی اجرا این کار تمام شه (مثل حلقه for ) یه شمارنده تعریف کن. تو event مورد نظر یه واحد بهش اضافه کن و چک کن که اگه به تعداد مورد نظرت رسیده بود متد timer1.Stop() رو صدا کن که دیگه اجرا نشه اون event، همون طور که میبینی اصلا نیازی به حلقه for نداری.

robat7
جمعه 21 آبان 1389, 20:21 عصر
راستش من از timer زياد استفاده نمي كنم چون برنامه را كند ميكند و اگر شما مي خواهيد اين كار را انجام دهيد بايد پس از اتمام نياز به تايمر آن را غير فعال نماييد

كامياب باشيد

bita_naz
شنبه 22 آبان 1389, 19:59 عصر
با تشکر از جوابهای دوستان .
من دارم یک سیمولاتور میسازم واسه همین نیاز دارم که اعمال کاربر رو شبیه سازی کنم . به این صورت که فرم ورود اطلاعاتی رو که کاربر باید پر کنه رو من میخام بوسیله یک نرم افزار پر کنم .

باید به تعداد مشخص کاری رو انجام بدم و بین هر بار چند ثانیه(مدت انتظار متغیر هستش) صبر کنم .از تایمر نمیشه استفاده کرد چون دقیقا برعکسه یعنی در زمانی مشخص کاری رو تکرار میکنه مثلا فرض کنید که برنامه شبیه ساز میخاد یک page رو چندین بار رفرش کنه و بین هر بار رفرش باید صبر کنه که page بعدی کاملا بالا بیاد پس زمان انتظارها متغیر هستن و در نتیجه از تایمر نمیشه استفاده کرد. برای این کار از چند نخی هم نتونستم استفاده کنم چون باعث میشه که کل برنامه در زمان انتظار هنگ کنه .

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

اینم تابع :



public static void PauseForMilliSeconds(int T)
{
DateTime TimeA = DateTime.Now;
DateTime TimeB = TimeA.AddMilliseconds((double)T);

while (TimeB >= TimeA)
{
System.Windows.Forms.Application.DoEvents();
TimeA = DateTime.Now;
}
}

debugger
یک شنبه 23 آبان 1389, 07:59 صبح
درسته کد بالا وقفه را به درستی ایجاد می کنه و برنامه هم هنگ نمی کنه

ولی cpu usage میشه 100 .

منم در برنامه ام در جاهای مختلفی باید وقفه بزارم . که باعث میشه فشار بیش از حدی به cpu بیاد

کدی که در زیر نوشتم هم وقفه را به درستی ایجاد می کند ولی این کد هم cpu usage را 100 میکنه



public void waittime(long maks)
{
int count = 0;
while (100 > 1)
{
Application.DoEvents();
count++;
if (count == maks)
{
break;
}
}
}


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

باید از system.threading.timer استفاده کنید



System.Threading.Timer timer;
System.Threading.TimerCallback cb = new System.Threading.TimerCallback (ProcessTimerEvent);
timer = new System.Threading.Timer (cb, time, 4000, 1000);

kamran00f
پنج شنبه 27 آبان 1389, 13:55 عصر
با تشکر از جوابهای دوستان .
من دارم یک سیمولاتور میسازم واسه همین نیاز دارم که اعمال کاربر رو شبیه سازی کنم . به این صورت که فرم ورود اطلاعاتی رو که کاربر باید پر کنه رو من میخام بوسیله یک نرم افزار پر کنم .

باید به تعداد مشخص کاری رو انجام بدم و بین هر بار چند ثانیه(مدت انتظار متغیر هستش) صبر کنم .از تایمر نمیشه استفاده کرد چون دقیقا برعکسه یعنی در زمانی مشخص کاری رو تکرار میکنه مثلا فرض کنید که برنامه شبیه ساز میخاد یک page رو چندین بار رفرش کنه و بین هر بار رفرش باید صبر کنه که page بعدی کاملا بالا بیاد پس زمان انتظارها متغیر هستن و در نتیجه از تایمر نمیشه استفاده کرد. برای این کار از چند نخی هم نتونستم استفاده کنم چون باعث میشه که کل برنامه در زمان انتظار هنگ کنه .

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

اینم تابع :



public static void PauseForMilliSeconds(int T)




{

DateTime TimeA = DateTime.Now;
DateTime TimeB = TimeA.AddMilliseconds((double)T);

while (TimeB >= TimeA)
{
System.Windows.Forms.Application.DoEvents();
TimeA = DateTime.Now;
}

}




نوشتن اینجور کدها اصلا جالب نیستن! چون به قول دوستمون cpu usage رو 100% میکنه. اگه دفعه میدونی قراره چقدر صبر کنی (همون طور که تو این کد نوشتی) باز هم از تایمر میشه استفاده کرد و به این شکل کد رو نوشت. یه Timer به اسم timer1 و رویداد timer1.Tick بسازی و یه int هم به اسم counter که بشمره چند بار حلقه انجام شه بعد تو برنامه:



int counter = 0;
Timer timer1 = new Timer();
timer1.Tick += new EventHandler(timer1.Tick);

int T = 1500; // inja yani masalan mikhaym kare morede nazar bad az 1500 ms anjam she

timer1.Interval = T;
timer1.Start();



حالا رویداد Tick رو برای timer1 اینجوری مینویسم



private void timer1_Tick (object sender, EventArgs e)
{
har kari ke lazeme bad az T mili sanie anjam she//
counter++;

if(counter<400)
{
counter = 0;
timer1.Stop();
}
}



اینجوری هر بار رویداد تیک بعد از هر چند میلی ثانیه که مشخص کردی اجرا میشه و فقط هم یه بار اجرا میشه. دیگه لازم نیست بزنی تو سر cpu تا اونقدر صبر کنه. تو این برنامه من فرض کردم بعد 400 بار قراره حلقه کارش تموم شه. تو میتونی هر جوری که خودت میدونی کی timer1 رو Stop کنی. اگه قراره هر دفعه هم مقداری که باید صبر کنه فقط کافیه خاصیت timer1.Interval رو همونقدر ست کنی. درضمن اینطوری کاری که تو رویداد tick انجام میشه تو یه نخ دیگه انجام میشه و برنامه در حین انجام اون کار (اگه زمان بر باشه) هنگ نمی کنه.

FastCode
پنج شنبه 27 آبان 1389, 14:01 عصر
راهی که به ذهن من میرسه استفاده از AutoResetEvent (http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx)
هست.
مزایا:
کد نویسی کمتر.
سرعت بیشتر.
دقت بیشتر.
قابلیت کنسل کردن.
استاندارد بودن.
معایب:
این و دیگه خودتون مدونید (بلد نیستید باهاش کار کنید.)

Javad_raouf
پنج شنبه 27 آبان 1389, 14:14 عصر
دوستان چرا مساله رو پیچیده می کنید
بهترین راه راهیه که دوستمون codelover فرمودند

System.Threading.Thread.Sleep(2000);
هر جا این کد نوشته بشه برنامه 2 ثانیه صبر می کنه
-----------------------------
این کد CPU Usage را 100 می کند:

while (TimeB >= TimeA)
{
System.Windows.Forms.Application.DoEvents();
TimeA = DateTime.Now;
}
ولی اگر همین کد را اینگونه بنویسیم مشکلی پیش نمی آید:

while (TimeB >= TimeA)
{
System.Windows.Forms.Application.DoEvents();
TimeA = DateTime.Now;
System.Threading.Thread.Sleep(1000)
}

bita_naz
پنج شنبه 27 آبان 1389, 18:27 عصر
راه صحیح همون استفاده از چند نخی هست
ولی بازم میگم برای پروژه من به هر حال از Timer نمیشه استفاده کرد چون زمانهای وقفه متغییر هستن. برنامه باید یک کاری شبیه listening انجام بده ولی برای یک رویداد خاص از اون برنامه مادر و اصلا معلوم نیست چه موقع اون رویداد رخ میده.

kamran00f
پنج شنبه 27 آبان 1389, 21:21 عصر
راه صحیح همون استفاده از چند نخی هست
ولی بازم میگم برای پروژه من به هر حال از Timer نمیشه استفاده کرد چون زمانهای وقفه متغییر هستن. برنامه باید یک کاری شبیه listening انجام بده ولی برای یک رویداد خاص از اون برنامه مادر و اصلا معلوم نیست چه موقع اون رویداد رخ میده.

میشه هرجا که فهمیدی قراره چقدر منتظر باشه timer1.interval رو ست کنی، اینجوری زمان های وقفه تغییر میکنه. ولی درسته استفاده از system.threading.thread.sleep(int) راحت تره.

debugger
جمعه 28 آبان 1389, 00:40 صبح
عزیز دل وقتی از system.threading.thread.sleep استفاده می کنند برنامه هنگ میکنه

ما به وقفه ای نیاز داریم که برنامه هنگ نکنه

شما چرا این همه روی system.threading.thread.sleep پافشاری می کنید

FastCode
جمعه 28 آبان 1389, 07:51 صبح
خیلی خوشم میاد راه حل رو میگم کسی نگاه هم نمیکنه.انگار نه انگار که کلی توضیح دادی که اگر از فلان چیز استفاده کنی مشکلت تا فلان حد حل میشه.

bita_naz
جمعه 28 آبان 1389, 12:50 عصر
بعد از تمام این بحثها به این نتیجه رسیدم که بهترین راه تابع زیر هست . نه برنامه هنگ میکنه و نه به سیستم فشار میاره :


public static void PauseForMilliSeconds(int T)
{
DateTime TimeA = DateTime.Now;
DateTime TimeB = TimeA.AddMilliseconds((double)T);

while (TimeB >= TimeA)
{
System.Windows.Forms.Application.DoEvents();
TimeA = DateTime.Now;
System.Threading.Thread.Sleep(1);

}

kamran00f
جمعه 28 آبان 1389, 14:36 عصر
متاسفانه تو نوشتار نمیشه خوب منظورو رسوند. ببین این همون کاری که منظورت هست رو انجام میده؟

Felony
جمعه 28 آبان 1389, 15:15 عصر
حلقه شما داره تو Thread اصلی برنامه اجرا میشه ( Main Thread ) ، وقتی قراره وقفه ای رخ بده یعنی وقفه تو پردازش صف Main Thread رخ میده پس برنامه فریز میشه ، اون Application.DoEvents هم کار خاصی نمیکنه ، فقط به Main Thread میگه زمانی رو هم به پردازش پیغام های موجود تو صف اختصاص بده ، حالا این زمان کی و چقدر هست معلوم نیست و برای همین هم برنامه با همون کد Application.DoEvents هم به صورت عادی کار نمیکنه ، اگر تو پروژتون واقعا نیاز به ایجاد وقفه در حلقه دارید و راه حل دیگه ای هم ندارید بهتره یه کلاس Thread طراحی کنید که این کار رو براتون انجام بده تا بار پردازش حلقه و وقفه داخل اون از دوش Main Thread برداشته بشه .

@ به روز رسانی رابط کاربری برنامه بر عهده Main Thread هست و برای همین هست که وقفه در کار این Thread باعث فریز شدن رابط کاربری میشه .

Javad_raouf
جمعه 28 آبان 1389, 16:14 عصر
عزیز دل وقتی از system.threading.thread.sleep استفاده می کنند برنامه هنگ میکنه

ما به وقفه ای نیاز داریم که برنامه هنگ نکنه

شما چرا این همه روی system.threading.thread.sleep پافشاری می کنید
اونم قابل حله فقط باید یک نخ ساخت و توی اون کد رو نوشت

بعد از تمام این بحثها به این نتیجه رسیدم که بهترین راه تابع زیر هست . نه برنامه هنگ میکنه و نه به سیستم فشار میاره :

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

Javad_Darvish_Amiry
جمعه 28 آبان 1389, 19:05 عصر
خوب دوستای عزیز، یه خورده دقت کنین، وقفه تو هر نخی که باشه اون نخ sleep یعنی خواب یعنی لالا، خوب یه نخ دیگه واسه حلقه بساز همون ()Sleep خیلی عالیه، با cpu هم کاری نداره.