How to set time out for AsyncTask execution?

只谈情不闲聊 提交于 2019-12-24 14:55:56

问题


I have been trying to create time out while AsyncTask execution more than 1 minute. If the time up, then should exit with Notification.

This is my code:

private class GetLongLat extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        longlatDialog = new ProgressDialog(MainActivity.this);
        longlatDialog.setMessage("Fetching Data. Please wait..");
        longlatDialog.setCancelable(false);
        longlatDialog.show();

    }

    @Override
    protected Void doInBackground(Void... arg0) {

         GPSTracker gpsTracker;

         //This is the timer to set time out
         Timer timer = new Timer();
         timer.schedule(new TaskKiller(this), 3000);
         timer.cancel();

         do{
             gpsTracker = new GPSTracker(MainActivity.this);
             gpsTracker.getLocation();

         }while(!String.valueOf(gpsTracker.latitude).equals("0.0"));

        return null;
    }

    protected void onCancelled() {
     // do something, inform user etc.
        Toast.makeText(getApplicationContext(), "Failed getting long lat. Please check your internet connection", Toast.LENGTH_LONG).show();
        System.exit(1);
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        if (longlatDialog.isShowing())
            longlatDialog.dismiss();
    }

}

And this is a class called in doInBackground to set the time up.

class TaskKiller extends TimerTask {
 private AsyncTask<?, ?, ?> mTask;

  public TaskKiller(AsyncTask<?, ?, ?> task) {
    this.mTask = task;
  }

  public void run() {
     mTask.cancel(true);
  }
}

But when i run the code, nothing happen. I mean the progress dialog always run very long time.

EDIT I have edit my code to call GetLongLat something like this:

GetLongLat n = new GetLongLat();
n.execute();
try {

    n.get(3000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ExecutionException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (TimeoutException e) {
    // TODO Auto-generated catch block
    Toast.makeText(getApplicationContext(), "Failed getting long lat. Please check your internet connection", Toast.LENGTH_LONG).show();
    System.exit(1);
} 

But also, doesn't work.


回答1:


I think you can use AsyncTask.get()

GetLongLat n = new GetLongLat();
n.get(30000, TimeUnit.MILLISECONDS);

you will have to use the n.get in a separate Thread..

Edited: one more different method but not efficient.,

GetLongLat n = new GetLongLat();
n.execute(); 
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
   @Override
   public void run() {
       if ( n.getStatus() == AsyncTask.Status.RUNNING )
           n.cancel(true);
  }
 }, 30000 );



回答2:


why are you canceling the timer? just after calling schedule()?

Cancels the Timer and all scheduled tasks

timer.cancel(); should be removed. check docs for cancel()




回答3:


You can achieve this behaviour in many ways.

Here's an example using CountDownTimer

// Start your AsyncTask
private YourAsyncTask mTask = new YourAsyncTask().execute();

// Run a timer after you started the AsyncTask
new CountDownTimer(60000, 1000) {

    public void onTick(long millisUntilFinished) {
        // Do nothing
    }

    public void onFinish() {
        mTask.cancel(true);
    }

}.start();

You are cancelling the timer just after initiating it. You can do it like this too. But this type of busy waiting is not recommended at all.

@Override
protected Void doInBackground(Void... arg0) {

     GPSTracker gpsTracker;

     //This is the timer to set time out
     new CountDownTimer(60000, 1000) {

         public void onTick(long millisUntilFinished) {
             // Do nothing
         }

         public void onFinish() {
             // Set latitude to zero to finish the while loop outside.
             // gpsTracker.latitude = "0.0"; // Something like this
         }

     }.start();

     do{
         gpsTracker = new GPSTracker(MainActivity.this);
         gpsTracker.getLocation();

     }while(!String.valueOf(gpsTracker.latitude).equals("0.0"));

    return null;
}



回答4:


Here's another approach. In your doInBackground method, you can use System.currentTimeMillis to check whether 1 minute has elapsed or not.

protected Void doInBackground(Void... arg0) {

         GPSTracker gpsTracker;

         long startTime = System.currentTimeMillis();

         do{
             gpsTracker = new GPSTracker(MainActivity.this);
             gpsTracker.getLocation();

         }while(!String.valueOf(gpsTracker.latitude).equals("0.0")
                && ((System.currentTimeMillis() - startTime) <= 60000);//60000 millisecond = 1 minute

        return null;
}

`




回答5:


Just alter your code like this and check whether your async task is getting cancelled or not.

            GetLongLat getLongLatAsync = new GetLongLat();
            getLongLatAsync.execute();
            try {
            Handler handler = new Handler();
            /** 1st method **/
            handler.postDelayed(new Runnable()
             {
              @Override
              public void run() {
                 if (getLongLatAsync.getStatus() == AsyncTask.Status.RUNNING )
                  getLongLatAsync.cancel(true);
                }
              }, 3000 ); //3 Seconds
    /** 1st method ends **/
    /** second method */
            handler.post(new Runnable()
             {
              @Override
              public void run() {
        getLongLatAsync.get(3000, TimeUnit.MILLISECONDS);//You should run it in seperated thread or else it will block ui thread.
    }
    });
/** Second method ends**/
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (TimeoutException e) {
                // TODO Auto-generated catch block
                Toast.makeText(getApplicationContext(), "Failed getting long lat. Please check your internet connection", Toast.LENGTH_LONG).show();
            } 

and in the onCancelld method write your logic

@Override
protected void onCancelled() {
Log.d(TAG,"Asynctask has been cancelled.");
}


来源:https://stackoverflow.com/questions/36245777/how-to-set-time-out-for-asynctask-execution

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!