【问题标题】:How to set time out for AsyncTask execution?如何设置 AsyncTask 执行的超时时间?
【发布时间】:2016-07-14 17:37:51
【问题描述】:

我一直在尝试在 AsyncTask 执行超过 1 分钟时创建超时。如果时间到了,那么应该退出通知。

这是我的代码:

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();
    }

}

这是一个在 doInBackground 中调用的类来设置时间。

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

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

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

但是当我运行代码时,什么也没有发生。我的意思是进度对话框总是运行很长时间。

编辑 我已经编辑了我的代码以调用 GetLongLat,如下所示:

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);
} 

但是,也不起作用。

【问题讨论】:

标签: android android-asynctask


【解决方案1】:

我认为你可以使用 AsyncTask.get()

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

您将不得不在单独的线程中使用 n.get..

已编辑:另一种不同的方法,但效率不高。,

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 );

【讨论】:

  • 我已根据您的回答编辑了代码。我不知道,但不起作用。 @saran
  • @SamsulArifin 您面临的错误/问题是什么..?
  • @SamsulArifin 如果您仍然遇到问题,我已经编辑和更新了不同的方式..看到,但效率不高
  • @SamsulArifin 如果您打算使用我提到的任何一种方法,那么您首先必须删除代码中已经存在的超时部分......
【解决方案2】:

你为什么要取消计时器?刚打电话给schedule()?

取消定时器和所有计划任务

timer.cancel(); 应该被删除。检查docs 的取消()

【讨论】:

    【解决方案3】:

    您可以通过多种方式实现此行为。

    这是一个使用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();
    

    您在启动计时器后就取消了它。你也可以这样做。但是完全不推荐这种类型的忙等待。

    @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】:

      这是另一种方法。在您的doInBackground 方法中,您可以使用System.currentTimeMillis 检查1 分钟是否已过。

      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;
      }
      

      `

      【讨论】:

      • 那么,我可以在哪里放置超时时退出应用程序的代码?
      • 超时后,while循环会自动退出,null会从doInBackground方法返回,之后onPostExecute会被调用,你可以把代码放在那里。
      • 我也在尝试你的代码。而且我认为更有效率和效果。但是,我仍然混淆在超时和不在 onPostExeceute 之间进行检查。你有想法吗?
      • 我不明白你的问题。您能否详细说明i still confuse to check between time out and not in onPostExeute.@Samsul 是什么意思?
      【解决方案5】:

      只需像这样更改您的代码并检查您的异步任务是否被取消。

                  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();
                  } 
      

      在 onCancelld 方法中写下你的逻辑

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

      【讨论】:

      • 我一直在尝试您的代码。所有的。然后,同样的结果。我上面问的一点是当用户打开 GPS,然后自动加载 long 和 lat。但有时,用户的互联网连接速度很慢,所以如果用户在 1 分钟后无法加载 long lat。应用程序将退出。
      • 上述方法应该有效,除非您正在做一些不同的事情,因为它对我们有用!!!
      • 感谢您的回答。我已经找到了另一种方式。这个stackoverflow.com/questions/7882739/… 完美运行。但是您的代码也适用于不同的方法。再次感谢
      • 不错。我认为与我所写的答案相同,只是增加了一点味道。 ;)
      • 是的,可能是“处理程序”无法处理我的代码,应该替换为“线程”
      猜你喜欢
      • 2011-12-14
      • 2012-11-18
      • 2011-07-04
      • 2013-06-11
      • 1970-01-01
      • 2014-06-06
      • 2016-10-30
      • 1970-01-01
      相关资源
      最近更新 更多