بروز خطا
   [message]
اشتراک در سوال
رای ها
[dataList]
پرسش و پاسخ

نحوه متوقف کردن و ادامه دادن Thread

مدیریت گفتگو
Hossein Kurd 12 سال پیش
آخرین تغییر: 8 سال پیش

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

نظرات

Criss 11 سال پیش
من دارم کل انجن رو سرچ میکنم _ هنوز جواب درستی پیدا نکردم ! من یک کانتر دارم که شمارش معکوس انجام میده < قبل از اتمام کار ترد و تمام شدن شمارش معکوس جواب مسئله پیدا میشه < توی این مدت دوباره شمارش معکوس از اول اجرا میشه < اما همچنان ترد قبلی داره کار میکنه < و مقدار TextView پشت سر هم تغییر میکنه < که اصلا جالب نیست !

پاسخ‌ها 10

hamed 11 سال پیش

من این کار را می کنم. درست و غلطش را نمی دونم. یک متغیر تعریف می کنم و هر وقت خواستم درون ترد پروسه ای اجرا نشه اون را false می کنم. با این کار از درون خود ترد هم می ونم اون را کنترل کنم. به عنوان مثال:

 Thread thread = new Thread(new Runnable() {
 boolean bool = true;
                    
                    @Override
                    public void run() {
                        while (bool) {
                            try {
                                Thread.sleep(500);
                                G.HANDLER.post(new Runnable() {

                                    @Override
                                    public void run() {

                                        DownloadRequest request = downloadRequests.get(item.DownloadRequestIndex);
                                        int percent = request.getPercent();
                                        prgressBarItemStandardDownloading.setProgress(percent);
                                        txtStandardDownloadingPersent.setText("  " + percent + " %");
                                        if (percent == 100) {
                                            bool = false;
                                        }
                                    }
                                });
                            }
                            catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });
                thread.start();

نظرات

Criss 11 سال پیش
این برای زمانی خوب هست که کارشما باید تا اخر اتمام پیدا کنه
hamed 11 سال پیش
کریس جان سوال شما را دقیقا نفهمیدم. ایا این سوال اینجا با این لینک مرتبطه؟
Criss 11 سال پیش
نه اون مشکل قدیمی بود < که با الگوریتم حلش کردم < مشکلی که الان دارم < مربوط میشه به یک شمارش گر معکوس < که با شروع اکتیویتی شروع به کم شدن میکنه < حالا اگر ماهر لحظه بخواهیم ثانیه شمار رو از اول شروع کنیم باید یک بار دیگه ترد رو فراخوانی کنیم که این کار باعث میشه ترد پشت سر هم مقدار TextView رو تغییر بده
hamed 11 سال پیش
یه شمارش گر معکوس تو یکی از آموزش ها بود. یادم نیست چجوری بود ولی شاید ایده خوبی داشته باشه. یه نگاه بهش بندازید. ببخشید یکم دیرفهمم(هنوز نفهمیدم چی به چیه!) اما اگه اشتباه نکنم شما یه اکتیویتی دارید که یک شمارشگر معکوس با بالا آمدن آن شروع به کار می کنه. (خوب حالا یه سوال اینه که ساختار شمارشگر چجوریه؟ مثلا می تونه یک حلقه باشه که یک دستور وقفه داخل اون قرار می گیره و یا راه های دیگر) خوب حالا دقیقا اینکه شما مثلا می خواهید شمارش گر را ریست یا متوقف بکنید چه ربطی به اجرای مجدد ترد پیدا می کنه؟ شما می تونید برای ریست مقدار شمارش گر را از نو مقدار دهی کنید. و برای توقف هم درون حلقه یک شرط قرار بدهید که از حلقه بیاید بیرون و یا از while یا do-while استفاده کنید.
Criss 11 سال پیش

من یک شمارش معکوس دارم <

میخوام هر بار که متد زیر اجرا میشه < شمارش از ابتدا اغاز بشه < و شمارشی که از قبل شروع شده دیگه ادامه پیدا نکنه  !

  public void Counter() {
TextView txtCounter = (TextView) findViewById(R.id.txtcounter);

ThreadCounter thread_conter = new ThreadCounter();

thread_conter.setSecound(70);

thread_conter.setTextView(txtCounter);
thread_conter.start();

}

ترد هم بصورت زیر هست

 
public class ThreadCounter extends Thread {

private int secound;
private int counter;
private TextView textView;




public void setSecound(int value) {

secound = value;
counter = secound;

}


public void setTextView(TextView value) {

textView = value;
}


@Override
public void run() {


super.run();

while (counter >= 0) {
Log.i("LOG", "" + counter);

if (textView != null) {
G.HANDLER.post(new Runnable() {




@Override
public void run() {
int MIN = (int) Math.floor(counter / 60);
int SEC = (int) Math.floor(counter % 60);
String P_SEC = "";
String P_MIN = "";
if (SEC < 10) {
P_SEC = "0";
}
if (MIN < 10) {
P_MIN = "0";
}
textView.setText(P_MIN + MIN + ":" + P_SEC + SEC);

}
});

}

try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}

counter--;

}

}
}

 

نظرات

Criss 11 سال پیش
چطور میتونم تا تعریف یک متغیر از دستور While ، بریک کنم ؟ و دوباره از اول شروع کنم ؟
hamed 11 سال پیش
خوب حالا شد. البته من دو تا پیشنهاد الان با ذهنم می رسه که یه جورایی فعلا پاک کردن صورت مساله است. اول اینکه می تونید شیوه نوشتن تایمر را عوض کنید و اصلا اون را به صورت ترد نگذارید که داستان جدایی می شه. و دوم که اصولی تر به نظر می رسه اینه: شما در درجه اول txtCounter و thread_conter را به صورت غیرمحلی و خارج از متد تعریف کنید. به این ترتیب با هر بار تغییر محتوای thread_conter.setSecound(70);l می توانید شمارشگر را از نو راه اندازی کنید.
Criss 11 سال پیش
کمی سرچ کردم ، فکر کنم روش اول رو انتخاب کنم < فعلا دارم تست میکنم سورسش رو < فکر کنم این روش ، از روش استاد هم ساده تر باشه !
hamed 11 سال پیش
البته حواستون باشه که در این روش چون پردازش شمارش معکوس به صورت موازی با بخش های دیگر برنامتون پیش نمی ره یه خورده الگوریتم پیچیده تری را در کدهای برنامتون می طلبه. (البته بستگی به برنامتون هم داره)
Criss 11 سال پیش

خب چیزی که تجربه شد < اینه که ترد رو نمیشه Stop یا  Kill یا Destroy کرد

و ترد زمانی تموم میشه که خود به خود کارش تمومش بشه < مثلا اگر دستور For یا While وجود داشته باشه اون متغیر باید 0 بشه و حلقه به انتها برسه ، مگر اینکه شما اینقدر خلاق کد بزنید که بتونید کار حلقه رو در لحظه ایی که میخواهید متغیرش رو 0 کنید !

من مجبور شدم سورس رو بصورت زیر تغییر بدم < (همچنان چندین ترد اجرا میشه < اما اینبار روی خروجی خرابی به بار نمیاره! و با اینکه TextView رو هی پشت سر هم توسط چندین ترد مقدارش رو ست میکنه ، اما در ظاهر پیدا نیست!)

متد در اکتیوتی اصلی به این صورت تغییر کرد <

 public void Counter() {
TextView txtCounter = (TextView) findViewById(R.id.txtcounter);
ThreadCounter thread_conter = new ThreadCounter();
thread_conter.setTextView(txtCounter);
thread_conter.start();
}

و کلاس ترد هم به صورت زیر

در واقع آخرین مقدار از روی خود TextView دریافت میشه که بصورت پیشفرض برابر 60 هست

 
public class ThreadCounter extends Thread {


private int counter;
private TextView textView;



public void setTextView(TextView value) {
textView = value;
String txtcounter = textView.getText().toString();
counter = Integer.parseInt(txtcounter);
}


@Override
public void run() {

super.run();
while (counter >= 0) {
Log.i("LOG", "" + counter);
if (textView != null) {
G.HANDLER.post(new Runnable() {

@Override
public void run() {
textView.setText("" + counter);
}
});
}
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
counter--;
}
}
}

 

نظرات

Criss 11 سال پیش
ولی هنوز وقتی متد دوباره اجرا میشه < نمیتونیم مقدارش رو از اول برابر 60 قرار بدیم !
Criss 11 سال پیش

سلام دوستان

بلاخره موفق شدم ترم رو متوقف کنم

اما کد نویسی اون به کثیف ترین شکل ممکن انجام شده ! و البته ترد ها هر چنتا که اجرا شده باشند همه با هم متوقف می شوند <

ولی باز هم نیاز هست < بعد از توقف ترد ها < دوباره خود بخود یک ترد از 60 شمارش کنه < که این قسمتش رو هنوز ننوشتم !

 

# توی این روش یک Buttonداریم < که هم متد به اون دسترسی داره و هم کلاس ترد <

#ترد توی هر لحظه چک میکنه که مقدار Text درون Button  مقدارش 0 هست یا 1 < اگر 0 باشه اخرین شرط حلقه اجرا میشه و ترد متوقف میشه<

# اگر متد دوبار اجرا بشه برای بار دوم مقدار باتن از 1 به 0 تغییر میکنه که باعث میشه ترد از کار بوفته !

واسطه ی ما یک باتن هست !

> متد بصورت زیر تغییر کرده !

  public void Counter() {
timer = !timer;
Log.i("timer", "" + timer);
TextView txtCounter = (TextView) findViewById(R.id.txtcounter);
Button btnfalse = (Button) findViewById(R.id.Button35);
if (timer) {
btnfalse.setText("1");
} else {
btnfalse.setText("0");
}
ThreadCounter thread_conter = new ThreadCounter();
thread_conter.setTextView(txtCounter);
thread_conter.setbtnView(btnfalse);
thread_conter.start();
}

و کلاس ترد هم به صورت زیر !

 

public class ThreadCounter extends Thread {

private int counter;
private int falseable;
private TextView textView;
private Button btnView;

public void setTextView(TextView value) {
textView = value;

}


public void setbtnView(Button value) {
btnView = value;

}


@Override
public void run() {

super.run();
//-----------------------------------------------------
//آخرین مقدار عددی شمارش گر (تکست ویو) از اینجا دریافت میشه و هر باز توسط ترد یکی کم میشه
String txtcounter = textView.getText().toString();
counter = Integer.parseInt(txtcounter)
//-----------------------------------------------------
//تا زمانی که وایل داره کار میکنه ترد از کار نمیوفته!
while (counter >= 0) {
//-----------------------------------------------------
//همیشه چک میشه که مقدار باتن 0 هست یا 1 که اگر 0 باشه در ادامه ترد رو از کار میاندازیم
String txtfalseable = btnView.getText().toString();
falseable = Integer.parseInt(txtfalseable);
//-----------------------------------------------------
Log.i("LOG", "" + counter);
if (textView != null) {
G.HANDLER.post(new Runnable() {


@Override
public void run() {
//-----------------------------------------------------
//مقدار تکست ویو بصورت شمارش معکوس نمایش داده میشود
textView.setText("" + counter);
//-----------------------------------------------------
// اینجا تمام تردها متوقف می شوند اگر مقدار باتن که در بالا دریافت شده 0 باشد !

if (falseable == 0) {

counter = 0;
textView.setText("60");
}
//-----------------------------------------------------
}
});
}
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
counter--;
}
}
}

لطفا همکاری کنید < اگر کسی متوجه میشه این کد چی هست نظر بده < اگر هم بد خط هست < کمی توضیح بدم <

نظرات

ajn91 11 سال پیش
یادش بخیر سال قبل همین موقع ها بود خیلی سر این موضوع اذیت شدم در اخر از Timer استفاده کردم و مشکلم حل شد پرا از Timer استفاده نمیکنید؟
Criss 11 سال پیش
این زندگی چدر زود میگذره 3 روز شده که وقت نکردم به پروژه سر بزنم ! میشه نمونه سورس اماده اگر دارید به همین تاپیک اضاف کنید < ولی من سعی میکنم یه راهی برای خارج شدن از ترد پیدا کنم < اخرین سورسی که گذاشتم ترد رو متوقف میکنه !
ChookD1 8 سال پیش
سلام این کدی که شما گذاشتید ، در چه سطحی بودید اونوقت که این کد رو زدید ؟ بنظر من خیلی کد عالی ای زدید .
Criss 11 سال پیش

سلام دوستان <

حدود 2 ماه لپ تاپ نداشتم / ایمیلم هم که دی اکتیو شد !

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

من میخواستم برای بازی هنگ من یک تایمر تعریف کنم ، که کاربر بعد از این مدت بازی رو به اجبار تموم کنه یا GameOver بشه

مشکل با ترد داشتم < که متوقف نمیشد

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

ولی برای مشکلی که من داشتم < تونستم به یک روشی مشکل رو حل کنم <<

قبلا همه چیز رو بالا توضیح دادم <

اینجا فقط سورس هارو میزارم

     public void Counter() {
TextView txtCounter = (TextView) findViewById(R.id.txtcounter);
ThreadCounter thread_conter = new ThreadCounter();
thread_conter.setTextView(txtCounter);
thread_conter.setbtnView(btnfalse);
thread_conter.start();
}

متد کانتر که باعث میشه شمارش معکوس شروع بشه یا متوقف بشه  < برای تاثیر گذاشتن روی ترد لازم بود 2 تا عنصر رو به ترد بفرستیم !

کلاس ترد هیچ تغییری نمیکنه < همون سورس بالا میمونه < توی کلاس ترد اگر مقدار btnfalse برابر 0 باشه ترد از کار میوفته
 و اگر یک باشه همچنان مقدار قبلی txtcounter دریافت میشه و یکی ازش کم میشه

حالا کافیه ما مقدار btnfalse رو مقدار دهی کنیم و بعد از اون متد بالا رو صدا بزنیم < تا ترد طبق درخواست ما متوقف بشه یا شروع به شمارش معکوس کنه

بنابر این با هر بار کلیک روی دکمه btnNew

مقدار btnfalse تبدیل به 0 میشه

 btnfalse.setText("0");
Counter();

و با هربار کلیک شدن روی هر کدوم از حروف مقدار btnfalse تبدیل به 1 میشه

 if (btnfalse.getText().toString().equals("0")) {
btnfalse.setText("1");
Counter();
}

برای اینکه چندین ترد بوجود نیاد < از دستور IF استفاده شده <

 

مشکل حل شد < اما اصلا جالب نیست که از یک باتن روی ویو برای توقف کردن ترد استفاده شده <

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

 

نظرات

abdolsalam 11 سال پیش
منم همین مشکلو دارم، چرا نمیشه از متد stop یا متد interrupt استفاده کرد؟ هیچ راه دیگه نیست؟
nooriDeveloper 11 سال پیش
منم تقریبا همین مشکل رو دارم، مثلا برای من چند سوال چهار گزینه ای هستش که به هر کدوم 5 ثانیه وقت میده، وقتی کاربر گزینه ای رو انتخاب کرد باید بره سوال بعدی، ولی مشکل اینجاست چون thread متوقف نمیشه مثلا وقتی کاربر بعد از 3 ثانیه روجواب کلیک کرد، برای سوال بعد بجای 5 ثانیه، 2 ثانیه وقت داره. دوستان کمک کنید.
doost_fu 11 سال پیش
منم با این مشکل دارم همین الان بازم کارم گیرش افتاد ! لامصب این ترد خیلی کاریه ! تا کارش تموم نکنه ول کن نیست !!
Criss 11 سال پیش
ترد شما چه کاری رو انجام میده ؟ یک حلقه while ? یا یک حلقه for ؟ اون تکه از کد که مدام تکرار میشه رو بزارید راهنماییتون کنم
doost_fu 11 سال پیش
دوستمون nooriDveloper که سوالشون داخل نظر قبلی نوشته بودند ! مشکل اصلی من اینه که چجوری به thread بگم بی خیال ! دیگه ادامه نده ! یه سوال دیگه هم قبلا همین پایین نوشته بودم ! ممنون .
Criss 11 سال پیش
سوال پایینیتون که جواب داده شده < اما ترد رو نمیشه بهش گفت که متوقف بشه < تنها راه متوقف کردن این هست که کاری رو که داره انجام میده رو متوقف کنید تا اینکه کاری وجود نداشته باشه و ترد هم فعالیتی انجام نده < ترد شما چه کاری رو انجام میده ؟
doost_fu 11 سال پیش
اون مال یه برنامه دیگه بود که کلا عملکرد برنامه رو عوض کردم چون ترد بعد از یه زمان تاخیر باید یه موسیقی پخش میکرد و در جای دیگه بعد از گذشتن زمان باید intent میکرد به یه اکتیویتی دیگه ... ! کلا کنسل و عوض شد .
doost_fu 11 سال پیش
الان هم در نظر بگیرید یه progresbar داریم که با زدن یه دکمه صفر تا صد پر میکنه ( مثلا هر یک دهم ثانیه ، یک درصد ) و با thread این تاخیر بوجود اوردیم حالا اگه قبل از رسیدن به صد دوباره دکمه رو بزنیم دوبار با فاصله این کار ایجاد میشه و اگه دوباره بزنیم ... حالا نمیشه با زدن دکمه thread قبلی کنسل بشه و دوباره شروع کنه ! البته مشکل با تغییر مقدار های حلقه یک تا صد و مقدار پروگرس حل کردم ولی خب ... ! با تشکر
doost_fu 11 سال پیش

دوستان بلاخره راه منطقی برا stop کردن thread  چیه ؟ در حالت عادی و همچنین موقع خروج از اکتیویتی
و یه سوال دیگه "
غیر از thread.sleep و استفاده از thread چطوری میشه در بین انجام دستورات یک تاخیر یا وقفه ایجاد کرد ؟
مثلا خط اول کد ما اجرا شد حالا بگیم 10 ثانیه صبر کن و بعد برو خط بعد و ادامه بده !

باتشکر

نظرات

saeidhic 11 سال پیش

این رو هم امتحان کن:

         Handler handler = new Handler();
handler.postDelayed(new Runnable() {

@Override
public void run() {
//code haye shoma

}
},10000);

نظرات

Criss 11 سال پیش
این کد شما postDelayed هست < به متوقف شدم ترد مربوط نیست !
Criss 11 سال پیش
اشتباه شد < این پست شما برای پست بالای هست < که کاملا صحیح هست
Criss 11 سال پیش

doost_fu @  درواقع شما انتظار داری با هربار کلیک شدن روی باتن < پروگرسبار شما از صفر شروع کنه به پر شدن < حتی اگر 50% پر شده باشه و در هیمن حین کلیکی انجام بشه همون لحظه مقدار پروگرس صفر بشه و شروع به پر شدن کنه <

شما نمیتونید ترد رو متوقف کنید < ولی میتونید مقدار i که درون حلقه for هست رو 100 کنید < تا کار ترد تموم بشه <

 

الان سورس پروژه رو براتون آپلود میکنم <

این نمونه کار ترد با پروگرس بار هست

 

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

 

نظرات

doost_fu 11 سال پیش
خب من داخل سوالم نوشتم که فعلا همین کارو کردم با تشکر .
ChookD1 8 سال پیش
سلام ، بالاخره بعد از اینهمه سال نتیجه تون چی شد ؟ آیا ترد قابل متوقف کردن نیست ؟ من الان این سوال برام مطرح شده و درگیرش هستم ، ینی 3 سال حداقل از شما عقبم |:
116236 8 سال پیش

روش روتین متوقف کردن ترد به این شکله:


        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                while ( !thread.currentThread().isInterrupted()) {
                    try {
                            thread.sleep(1000); //این خط الزامی نیست
                            //To DO    
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        });
        thread.start();
        
        //هرجا خواستیم ترد متوقف شود، دستور زیر را اجرا می کنیم
        thread.interrupt();

نظرات

ChookD1 8 سال پیش
interrupt دقیقا کارش چیه ؟
ChookD1 8 سال پیش
سلام ، کار نمیده ، من اجرا شدن Thread رو دادم دست یک Button که اسمش هست : btn_start و اجرا شدن thread.interrupt رو دادم دست یک Button به اسم : btn_stop اما متاسفانه جواب نمیده . ترد همینجور به کار خودش ادامه میده .
ChookD1 8 سال پیش
اما خوشبختانه کرش هم نمیکنه .
116236 8 سال پیش

روش روتین متوقف کردن ترد به این شکله:


        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                while ( !thread.currentThread().isInterrupted()) {
                    try {
                            thread.sleep(1000); //این خط الزامی نیست
                            //To DO    
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                        break;
                    }
                }
            }
        });
        thread.start();
        
        //هرجا خواستیم ترد متوقف شود، دستور زیر را اجرا می کنیم
        thread.interrupt();

نظرات

ChookD1 8 سال پیش
در داکیومنتی نوشته بود که اگه interrupt برای Thread هایی استفاده بشه که در اونها sleep ، wait (و شاید موارد مشابه دیگه ای ) باشه ، دستور interrupt براتون جوا نمیده . در اینجا هم ما داریم از sleep استفاده میکنیم و همونطور که امتحان کردم نمیشه ازش جواب گرفت .
116236 8 سال پیش
من این کد رو داخل یه نرم افزار استفاده کردم، مشکلی هم نداشته. برای شما چه مشکلی وجود داشت؟
ChookD1 8 سال پیش
درواقع stop نمیشه . زمانی که میخوایم متد thread رو intrrupt کنیم ، هیچ اتفاقی نمیفته
ChookD1 8 سال پیش
دستور intrrupt رو توی کلید دیگه ای گذاشتم ، وقتی روش میزنی هیچ اتفاقی نمیفته ، اما یه چیزی لوگ میشه ، چیزی که داره به خط 47 اشاره میکنه و خط 47 این دستور هست : Thread.sleep(300); نمیدونم مشکل از کجا باشه
116236 8 سال پیش
خب احتمالا داره از این خط خطا میگیره. ولی چون تووی بلک try نوشته شده نرم افزار کرش نمی کنه. اگه متن ارور رو بفرستید شاید بتونم کمک کنم

پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .