MoHammaD ReZa DehGhani
MoHammaD ReZa DehGhani

Reputation: 585

How set a timeout for my thread Handler method?

This is my function who run a code every 2.5 seconds and check if a value seted to the true my progress will gone and ...

mHandler = new Handler();
    continue_or_stop = true;
    new Thread(new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (continue_or_stop) {
                try {
                    Thread.sleep(2500); // every 2.5 seconds
                    mHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            if (sp.getFromPreferences("state_update").equals("true")) {

                                progress_main.setVisibility(View.GONE);
                                layout_main.setVisibility(View.VISIBLE);
                                btn_save_send.setVisibility(View.GONE);


                                getOutputs();

                                MDToast.makeText(getActivity(), "وضعیت دستگاه با موفقیت بروزرسانی شد", Toast.LENGTH_LONG, MDToast.TYPE_SUCCESS).show();

                                sp.saveToPreferences("state_update", "false");

                                Intent intent = new Intent(getContext(), MainActivity.class);
                                startActivity(intent);

                            }

                            // you can set continue_or_stop to false, for stop
                        }
                    });
                } catch (Exception e) {
                    // TODO: handle exception
                }
            }
        }
    }).start();

now i want a time out for this method if the value not seted to true after a (for example 12 seconds) progress should gone and Toast it to user that something goes wrong and try again

Upvotes: 2

Views: 1137

Answers (2)

LppEdd
LppEdd

Reputation: 21144

Apparently this is more Android oriented, but I'll answer in general terms. And the other answer seems lacking the "12 seconds" timeout.

Well, you cannot really terminate a Thread immediatly, or forcely. Consider a Thread like a person, you need to kindly request him to terminate what he's doing. If he is able to do that, he will terminate, if not he will continue with its task.

As you're building the implementation of the task, you can check if someone asked you to terminate, with a special flag

Thread#isInterrupted()

Now, for this kind of thing using an ExecutorService is the better option, as it returns a Future<T> which can be canceled. E.g.

final ExecutorService executorService = ExecutorService.newSingleThreadExecutor();
final Future<?> future = executorService.submit(runnable);

You can then say to the Future "I want the result (which in your case is nothing), but with a timeout"

try {
   future.get(12, TimeUnit.SECONDS);
} catch (final TimeoutException e) {
   future.cancel(true);
}

The cancel(true) method call will set the interrupted flag of the Thread.
Now, maintaining the code you already have, you might simply want to replace

while (continue_or_stop)

with

while (!Thread.currentThread().isInterrupted())

Adjust to your needs.

Upvotes: 1

frogatto
frogatto

Reputation: 29285

You can check for the timeout based on the number of trials. Also using thread and Thread.sleep for running a periodic task is not a good practice.

To run a periodic task, you can post a Runnable to a Handler with some delay using postDelayed method.

private Handler mHandler = new Handler();
private int mTrials = 0;
private Runnable mPeriodicTask = new Runnable() {
    public void run() {
        // Do the check

        mTrials += 1;
        if (mTrials == /* timeout number */) {
            // timeout
        } else {
            mHandler.postDelayed(this, 2500);
        }
    }
}

To run the task:

mHandler.postDelayed(mPeriodicTask, 2500);

Upvotes: 1

Related Questions