3

I have an app with an httprequest. I wanted to set a timeout for that request, and since I can't control de DNS timeout a user from stackoverflow suggested to create a Thread with a timer to cancel the request after a certain time, and that's what I'm doing.

In my new Thread I use Thread.sleep to wait 30 seconds and, when that time finishes, cancel the request if it hasn't ended, but my Thread never wakes up. This is my code:

private Thread timeout_request = new Thread(new Runnable() {
    public void run() {
        try{
            Log.d(TAG, "Thread start");
            Thread.sleep(30000);
            Log.d(TAG, "Thread awake");
            if(!httprequest_finished){
                request_aborted = true;
                mHttpClient.getConnectionManager().shutdown();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
});

public String sendData(String token){
    ...
    timeout_request.start();
    Log.i(TAG, "Sending request");
    final HttpResponse resp = httpClient.execute(post);
    Log.i(TAG, "Execute finished");
    if(request_aborted) return null;
    httprequest_finished = true;
    ...
}

If I execute the sendData function without internet connection the log shows "Sending request" and "Thread start", but doesn't show "Thread awake" or "Execute finished" (I've waited like 5 minutes). Why is that?

------ EDIT ------

By the way, I don't know if it matters, but I'm using ThreadSafeClientConnManager in my connection.

I've tested a few thing:

1- Replace HttpResponse resp = httpClient.execute(post) with while(!request_aborted). The thread awakes (it works).

2- Use mHandler.postDelayed(r, 30000) instead of a Thread. I'm still executing httpClient.execute(post). Result: the Runnable is NOT launched.

private Handler mHandler = new Handler();
private Runnable r = new Runnable() {
    public void run() {
        Log.d(TAG, "Runnable()");
        if(!httprequest_finished){
            request_aborted = true;
            mHttpClient.getConnectionManager().shutdown();
        }
    }
};

3- Use mHandler.postDelayed(r, 30000) instead of a Thread. Replace HttpResponse resp = httpClient.execute(post) with while(!request_aborted). Result: the Runnable is NOT launched.

So the thread works if I'm not executing the http request, but the handler never works. I noticed these lines in my log:

threadid=3: reacting to signal 3
Wrote stack traces to '/data/anr/traces.txt'
threadid=3: reacting to signal 3
Wrote stack traces to '/data/anr/traces.txt'

This appears 6 or 7 seconds after executing the thread or setting the handler. I've tried to use:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
            Log.e("Alert","Lets See if it Works !!!");
        }
    });

But the log never shows "Lets See if it Works !!!". I looked the traces.txt file and I don't understand what it's saying -.-

PX Developer
  • 8,065
  • 7
  • 42
  • 66
  • Cant u use :"HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000); //Timeout Limit" – Name is Nilay Sep 28 '12 at 08:05
  • That doesn't work for DNS resolution. http://stackoverflow.com/questions/12627001/android-connection-timeout-not-working-connection-waits-forever – PX Developer Sep 28 '12 at 08:32

2 Answers2

0

I have tested the following code:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication1;

/**
 *
 * @author paro
 */
public class JavaApplication1 {

    public boolean req_aborted = false;
    public Thread timeout_request = new Thread(new Runnable() {
    public void run() {
        try{
            System.out.println("start");
            Thread.sleep(30000);
            System.out.println("awake");
            if(req_aborted ==false)
            {
                req_aborted = true;
                System.out.println("flag change");
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
});
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        JavaApplication1 jap = new JavaApplication1();
        jap.timeout_request.start();
        System.out.println("requset started");
        if(jap.req_aborted)
        {
            System.out.println("flag is true now");
        }
    }
}

and the output is

requset started
start
awake
flag change

seems that no problem with the thread related part of your code.

and your code's logic says it should print "awake". seems that you are having problem with the following statement

final HttpResponse resp = httpClient.execute(post);
Tudor
  • 61,523
  • 12
  • 102
  • 142
Debobroto Das
  • 834
  • 6
  • 16
  • The only thing I can think of is that the request (httpClient.execute(post)) uses all the CPU and my thread isn't executed, but that would mean Android's design is really bad (unless there is an option to change it). – PX Developer Sep 28 '12 at 08:36
  • I would think it unlikely that a POST request would eat up all the CPU, but maybe that's just me and Android HHTP is indeed cr... bad. – Martin James Sep 28 '12 at 08:41
  • Yes, I find it really unlikely... I'll keep trying things. – PX Developer Sep 28 '12 at 08:44
0

Rather than using Thread.sleep I think you should be using Handler.postDelayed. Have a look at the documentation.

Something like:

Handler mHandler = new Handler();
...
mhandler.postDelayed(new Runnable() {
    public void run() {
        if(!httprequest_finished){
            request_aborted = true;
            mHttpClient.getConnectionManager().shutdown();
        }
    }
}, 30000);

This will execute the passed in Runnable after the specified delay.

dave.c
  • 10,910
  • 5
  • 39
  • 62