Android - एक AsyncTask के लिए टाइमआउट सेट करना?


125

मेरे पास एक 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, एक नया हैंडलर शुरू किया जाता है जो AsyncTask30 सेकंड के बाद रद्द कर देगा यदि यह अभी भी चल रहा है।

क्या यह एक अच्छा तरीका है? या वहाँ कुछ बनाया है AsyncTaskकि इस उद्देश्य के लिए बेहतर अनुकूल है?


18
कई अलग-अलग तरीकों की कोशिश करने के बाद, मैंने निष्कर्ष निकाला कि आपके प्रश्न का स्वीकृत उत्तर होना चाहिए।
JohnEye

इस सवाल के लिए धन्यवाद कि मैं वास्तव में एक ही मुद्दे पर गिर गया और आपके कोड ऑफ कोड ने मुझे +1 किया
अहमद द्वैयक 'वारलॉक'

1
आपका प्रश्न अपने आप में एक अच्छा उत्तर है +50 :)
कार्तिक कुलंजी 10

जवाबों:


44

हाँ, AsyncTask.get () है

myDownloader.get(30000, TimeUnit.MILLISECONDS);

ध्यान दें कि मुख्य थ्रेड (AKA। UI थ्रेड) में इसे कॉल करने से निष्पादन अवरुद्ध हो जाएगा, आपको संभवतः इसे एक अलग थ्रेड में कॉल करने की आवश्यकता है।


9
ऐसा लगता है कि यदि यह टाइमआउट विधि मुख्य UI थ्रेड पर चलती है, तो AsyncTask का उपयोग करने के उद्देश्य को पराजित करता है ... केवल handlerअपने प्रश्न में वर्णित दृष्टिकोण का उपयोग क्यों नहीं करता? ज्यादा सीधा लगता है क्योंकि हैंडलर के रननेबल को चलाने के इंतजार में यूआई थ्रेड फ्रीज नहीं होता ...
जेक विल्सन

ठीक है धन्यवाद, मुझे यकीन नहीं था कि यह करने के लिए एक उचित तरीका था या नहीं।
जेक विल्सन

3
मुझे समझ में नहीं आता है कि आप दूसरे धागे में क्यों कहते हैं। यह अजीब लग रहा है क्योंकि AsyncTask अपने आप में एक प्रकार का धागा है। मुझे लगता है कि जकोबुड का समाधान अधिक ठीक है।
पन्नाधाय

मुझे लगता है कि .get () पॉज़िक्स थ्रेड जॉइन के समान है, जहाँ उद्देश्य थ्रेड के पूरा होने की प्रतीक्षा करना है। आपके मामले में यह एक टाइमआउट के रूप में कार्य करता है, जो एक परिस्थितिजन्य संपत्ति है। यही कारण है कि आपको कॉल करने की आवश्यकता है। () हैंडलर से या दूसरे धागे से मुख्य यूआई ब्लॉकिंग से बचने के लिए
कॉन्स्टेंटाइन समोलेन्को

2
मुझे पता है कि यह वर्षों बाद है, लेकिन यह अभी भी एंड्रॉइड में नहीं बनाया गया है इसलिए मैंने एक समर्थन वर्ग बनाया है। मुझे उम्मीद है कि यह किसी को बाहर करने में मदद करता है। gist.github.com/scottTomaszewski/…
स्कॉट

20

मामले में, आपका डाउनलोडर एक URL कनेक्शन के लिए आधारित है, आपके पास कई पैरामीटर हैं जो आपको जटिल कोड के बिना टाइमआउट को परिभाषित करने में मदद कर सकते हैं:

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

  urlc.setConnectTimeout(15000);

  urlc.setReadTimeout(15000);

यदि आप इस कोड को अपने async कार्य में लाते हैं, तो यह ठीक है।

Read Timeout ’एक बुरे नेटवर्क का हस्तांतरण के साथ-साथ परीक्षण करना है।

'कनेक्शन टाइमआउट' को केवल परीक्षण के लिए बुलाया जाता है कि सर्वर ऊपर है या नहीं।


1
मैं समझौते में हूं। इस दृष्टिकोण का उपयोग सरल है, और यह वास्तव में समय समाप्त होने पर कनेक्शन को समाप्त कर देता है। AsyncTask.get () दृष्टिकोण का उपयोग करके आपको केवल सूचित किया जाता है कि समय सीमा समाप्त हो गई है, लेकिन डाउनलोड अभी भी संसाधित किया जा रहा है, और वास्तव में बाद में पूरा हो सकता है - जिससे कोड में अधिक जटिलताएं हो सकती हैं। धन्यवाद।
चकित

कृपया ध्यान रखें कि बहुत धीमे इंटरनेट कनेक्शन पर बहुत सारे थ्रेड्स का उपयोग करते समय यह पर्याप्त नहीं है। अधिक जानकारी: leafromjavaheap.blogspot.nl/2013/12/… और thushw.blogspot.nl/2010/10/…
Kapitein Witbaard

20

OnPreExecute () विधि में AsyncTask के लिए विस्तारित वर्ग की ओर CountDownTimer वर्ग का उपयोग करें:

मुख्य लाभ, वर्ग में आंतरिक रूप से किए गए Async निगरानी।

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

ChangeDownTimer (7000, 7000) -> CountDownTimer (7000, 1000) को उदाहरण के लिए बदल दें और यह ऑनफिनिश () को कॉल करने से पहले 6 बार onTick () कॉल करेगा। यह अच्छा है अगर आप कुछ निगरानी जोड़ना चाहते हैं।

इस पेज में मुझे मिली सभी अच्छी सलाह के लिए धन्यवाद :-)


2

मुझे नहीं लगता कि AsyncTask में ऐसा कुछ भी बनाया गया है। आपका दृष्टिकोण एक अच्छा लगता है। जब यूआई थ्रेड इसे रद्द कर देता है, तो इस पद्धति को समाप्त करने के लिए अपने AsyncTask के doInBackground पद्धति में समय-समय पर isCancelled () के मान की जांच करना सुनिश्चित करें।

यदि आप किसी कारण से हैंडलर का उपयोग करने से बचना चाहते हैं, तो आप समय-समय पर अपने AsyncTask के भीतर System.currentTimeMillis की जांच कर सकते हैं और टाइमआउट से बाहर निकल सकते हैं, हालांकि मुझे आपका समाधान बेहतर लगता है क्योंकि यह वास्तव में थ्रेड को बाधित कर सकता है।


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

         }

2
कुछ स्पष्टीकरण के साथ
सैफ आसिफ

0

आप रद्दीकरण को और अधिक मजबूत बनाने के लिए एक और शर्त रख सकते हैं। जैसे,

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

0

प्रश्न से प्रेरित होकर मैंने एक ऐसी विधि लिखी है जो कुछ पृष्ठभूमि कार्य 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;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.