1

I have an AsyncTask which I am using to create a Socket connection. Within my doInBackground() method, I have:

Socket socket = new Socket(HOST_NAME, PORT_NUMBER);

For my case, this line of code hangs when I try to connect via a cellular network. It never finishes executing and eventually the app crashes. Because the information from the Server was necessary to me, I did something like this:

AttemptConnection attemptConnection = new AttemptConnection(); // this is the AsyncTask
attemptConnection.execute().get();

Now I realize this is bad because the purpose of AsyncTask is to run parallel to the main thread and this is halting processing on the main thread. However, my app can't really go anywhere until the information from the Server is acquired so I kind of NEED this AsyncTask to finish.

Because the Socket connection fails and hangs some times though, there are cases where this causes freezes on my device and an eventual crash of my app. So I want something better. The solution I came up with is:

attemptConnection.execute();
try {
    Thread.sleep(3000);
} catch (Exception e) {
}
attemptConnection.cancel(); 

But I wonder if this is any better? I can't cancel the process internally because the try / catch that should catch errors with the Socket connection is never reached. The code hangs there and no errors are ever caught. But the above idea also seems like a really hacky way to do it; I'm wondering if this approach is as bad as my gut tells me it is, and if so, what are some better ways to handle this?

mike
  • 1,318
  • 3
  • 21
  • 41

1 Answers1

2

In general, you must code your ASyncTask so that it cannot hang indefinitely.

In your specific case, you can achieve this by specifying a timeout (of a few seconds, perhaps) when you create the Socket. This will force an exception to be thrown if the Socket connection cannot be established in a reasonable time. See Setting a timeout for socket operations for guidance on how to do this.

Of course, regardless of whether the connection succeeds or fails, you should never block your main thread waiting for the result. You should send the result from the ASyncTask through the usual way, by returning a result from doInBackground().

Community
  • 1
  • 1
Graham Borland
  • 60,055
  • 21
  • 138
  • 179
  • I wonder, I know it's bad practice, but since the AsyncTask is at the end of my main thread anyway, and all that needs to be done is the `Socket` stuff, is it still bad practice to block execution of the main thread with this timeout set, if I basically know the run time of the AsyncTask can't possibly exceed a few seconds? Is there a better alternative? – mike Jun 19 '14 at 22:06
  • 1
    Yes, it is still bad practice. Truly horrendous practice, in fact. You have no way of knowing it's at "the end" of your main thread; your app's lifecycle methods could be called by the system at any point. The better alternative is for the background task to communicate with the main thread through the proper mechanism, which in this case is to return a result from `doInBackground()`. – Graham Borland Jun 19 '14 at 22:13