Android - 为异步任务设置超时?

发布于 2024-12-12 00:29:48 字数 593 浏览 0 评论 0原文

我执行一个 AsyncTask 类,它从网站下载大量数据。

如果最终用户在使用时数据连接非常慢或不稳定,我希望在一段时间后使 AsyncTask 超时。我的第一个方法是这样的:

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

启动 AsyncTask 后,启动一个新的处理程序,如果它仍在运行,它将在 30 秒后取消 AsyncTask

这是一个好方法吗?或者 AsyncTask 中是否内置了更适合此目的的内容?

I have an AsyncTask class that I execute that downloads a big list of data from a website.

In the case that the end user has a very slow or spotty data connection at the time of use, I'd like to make the AsyncTask timeout after a period of time. My first approach to this is like so:

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

After starting the AsyncTask, a new handler is started that will cancel the AsyncTask after 30 seconds if it's still running.

Is this a good approach? Or is there something built into AsyncTask that is better suited for this purpose?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

一身软味 2024-12-19 00:29:48

是的,有 AsyncTask.get()

myDownloader.get(30000, TimeUnit.MILLISECONDS);

请注意,通过在主线程(又名 UI 线程)中调用此函数将阻止执行,您可能需要在单独的线程中调用它。

Yes, there is AsyncTask.get()

myDownloader.get(30000, TimeUnit.MILLISECONDS);

Note that by calling this in main thread (AKA. UI thread) will block execution, You probably need call it in a separate thread.

梦里梦着梦中梦 2024-12-19 00:29:48

在 onPreExecute() 方法中的 AsyncTask 扩展类中使用 CountDownTimer 类:

主要优点是,异步监控在类内部完成。

public class YouExtendedClass extends AsyncTask<String,Integer,String> {
...
public YouExtendedClass asyncObject;   // as CountDownTimer has similar method -> to prevent shadowing
...
@Override
protected void onPreExecute() {
    asyncObject = this;
    new CountDownTimer(7000, 7000) {
        public void onTick(long millisUntilFinished) {
            // You can monitor the progress here as well by changing the onTick() time
        }
        public void onFinish() {
            // stop async task if not in progress
            if (asyncObject.getStatus() == AsyncTask.Status.RUNNING) {
                asyncObject.cancel(false);
                // Add any specific task you wish to do as your extended class variable works here as well.
            }
        }
    }.start();
...

更改 CountDownTimer(7000, 7000) ->例如 CountDownTimer(7000, 1000),它会在调用 onFinish() 之前调用 onTick() 6 次。如果您想添加一些监控,这很好。

感谢我在本页中得到的所有好建议:-)

Use CountDownTimer Class in side the extended class for AsyncTask in the onPreExecute() method:

Main advantage, the Async monitoring done internally in the class.

public class YouExtendedClass extends AsyncTask<String,Integer,String> {
...
public YouExtendedClass asyncObject;   // as CountDownTimer has similar method -> to prevent shadowing
...
@Override
protected void onPreExecute() {
    asyncObject = this;
    new CountDownTimer(7000, 7000) {
        public void onTick(long millisUntilFinished) {
            // You can monitor the progress here as well by changing the onTick() time
        }
        public void onFinish() {
            // stop async task if not in progress
            if (asyncObject.getStatus() == AsyncTask.Status.RUNNING) {
                asyncObject.cancel(false);
                // Add any specific task you wish to do as your extended class variable works here as well.
            }
        }
    }.start();
...

change CountDownTimer(7000, 7000) -> CountDownTimer(7000, 1000) for example and it will call onTick() 6 times before calling onFinish(). This is good if you want to add some monitoring.

Thanks for all the good advice I got in this page :-)

疏忽 2024-12-19 00:29:48

在这种情况下,您的下载器基于 URL 连接,您有许多参数可以帮助您定义超时,而无需复杂的代码:

  HttpURLConnection urlc = (HttpURLConnection) url.openConnection();

  urlc.setConnectTimeout(15000);

  urlc.setReadTimeout(15000);

如果您只是将此代码带入异步任务中,那就可以了。

“读取超时”是为了测试传输过程中网络状况是否良好。

“连接超时”仅在开始时调用以测试服务器是否启动。

In the case, your downloader is based upon an for an URL connection, you have a number of parameters that could help you to define a timeout without complex code:

  HttpURLConnection urlc = (HttpURLConnection) url.openConnection();

  urlc.setConnectTimeout(15000);

  urlc.setReadTimeout(15000);

If you just bring this code into your async task, it is ok.

'Read Timeout' is to test a bad network all along the transfer.

'Connection Timeout' is only called at the beginning to test if the server is up or not.

月光色 2024-12-19 00:29:48

我认为 AsyncTask 中没有内置类似的东西。你的方法似乎是一个好方法。只需确保定期检查 AsyncTask 的 doInBackground 方法中 isCancelled() 的值,以便在 UI 线程取消该方法后结束该方法。

如果您出于某种原因想避免使用处理程序,您可以在 AsyncTask 中定期检查 System.currentTimeMillis 并在超时时退出,尽管我更喜欢您的解决方案,因为它实际上可以中断线程。

I don't think there's anything like that built into AsyncTask. Your approach seems to be a good one. Just be sure to periodically check the value of isCancelled() in your AsyncTask's doInBackground method to end this method once the UI thread cancels it.

If you want to avoid using the handler for some reason, you could check System.currentTimeMillis periodically within your AsyncTask and exit on timeout, although I like your solution better since it can actually interrupt the thread.

娇妻 2024-12-19 00:29:48
         Context mContext;

         @Override
         protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
                                    mContext = this;

            //async task
            final RunTask tsk = new RunTask (); 
            tsk.execute();

            //setting timeout thread for async task
            Thread thread1 = new Thread(){
            public void run(){
                try {
                    tsk.get(30000, TimeUnit.MILLISECONDS);  //set time in milisecond(in this timeout is 30 seconds

                } catch (Exception e) {
                    tsk.cancel(true);                           
                    ((Activity) mContext).runOnUiThread(new Runnable()
                    {
                         @SuppressLint("ShowToast")
                        public void run()
                         {
                            Toast.makeText(mContext, "Time Out.", Toast.LENGTH_LONG).show();
                            finish(); //will close the current activity comment if you don't want to close current activity.                                
                         }
                    });
                }
            }
        };
        thread1.start();

         }
         Context mContext;

         @Override
         protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
                                    mContext = this;

            //async task
            final RunTask tsk = new RunTask (); 
            tsk.execute();

            //setting timeout thread for async task
            Thread thread1 = new Thread(){
            public void run(){
                try {
                    tsk.get(30000, TimeUnit.MILLISECONDS);  //set time in milisecond(in this timeout is 30 seconds

                } catch (Exception e) {
                    tsk.cancel(true);                           
                    ((Activity) mContext).runOnUiThread(new Runnable()
                    {
                         @SuppressLint("ShowToast")
                        public void run()
                         {
                            Toast.makeText(mContext, "Time Out.", Toast.LENGTH_LONG).show();
                            finish(); //will close the current activity comment if you don't want to close current activity.                                
                         }
                    });
                }
            }
        };
        thread1.start();

         }
娇柔作态 2024-12-19 00:29:48

您可以再添加一个条件以使取消更加稳健。例如,

 if (downloader.getStatus() == AsyncTask.Status.RUNNING || downloader.getStatus() == AsyncTask.Status.PENDING)
     downloader.cancel(true);

You can put one more condition to make cancellation more robust. e.g.,

 if (downloader.getStatus() == AsyncTask.Status.RUNNING || downloader.getStatus() == AsyncTask.Status.PENDING)
     downloader.cancel(true);
爱给你人给你 2024-12-19 00:29:48

受问题启发,我编写了一种方法,通过 AsyncTask 执行一些后台任务,如果处理时间超过 LOADING_TIMEOUT,则会出现一个重试的警报对话框。

public void loadData()
    {
        final Load loadUserList=new Load();
        loadUserList.execute();
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (loadUserList.getStatus() == AsyncTask.Status.RUNNING) {
                    loadUserList.cancel(true);
                    pDialog.cancel();
                    new AlertDialog.Builder(UserList.this)
                            .setTitle("Error..!")
                            .setMessage("Sorry you dont have proper net connectivity..!\nCheck your internet settings or retry.")
                            .setCancelable(false)
                            .setPositiveButton("Retry", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    loadData();
                                }
                            })
                            .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                                @Override


                      public void onClick(DialogInterface dialogInterface, int i) {
                                System.exit(0);
                            }
                        })
                        .show();
            }
        }
    }, LOADING_TIMEOUT);
    return;
}

Inspiring from question I have written a method which do some background task via AsyncTask and if processing takes more then LOADING_TIMEOUT then an alert dialogue to retry will appear.

public void loadData()
    {
        final Load loadUserList=new Load();
        loadUserList.execute();
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (loadUserList.getStatus() == AsyncTask.Status.RUNNING) {
                    loadUserList.cancel(true);
                    pDialog.cancel();
                    new AlertDialog.Builder(UserList.this)
                            .setTitle("Error..!")
                            .setMessage("Sorry you dont have proper net connectivity..!\nCheck your internet settings or retry.")
                            .setCancelable(false)
                            .setPositiveButton("Retry", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    loadData();
                                }
                            })
                            .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                                @Override


                      public void onClick(DialogInterface dialogInterface, int i) {
                                System.exit(0);
                            }
                        })
                        .show();
            }
        }
    }, LOADING_TIMEOUT);
    return;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文