gnychis
gnychis

Reputation: 7555

communication with AsyncTask thread? Handler not working?

I have my main UI, and I have an AsyncTask running. I want to communicate to the AsyncTask to have it run something on the non-UI thread. So what I tried doing was:

protected class WifiMon extends AsyncTask<Context, Integer, String>
{
    Context parent;
    CoexiSyst coexisyst;
    private static final String WIMON_TAG = "WiFiMonitor";
    private int PCAP_HDR_SIZE = 16;
    private int _scan_pkts_left;

    public Handler _handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            // We invoke a scan, and then read in all of the packets
            // captured from the scan.
            if(msg.obj == ThreadMessages.WIFI_SCAN_START) {
                Log.d(TAG, "Got message to start Wifi scan");
                int start_rxpkts = getRxPacketCount();
                runCommand("/data/data/com.gnychis.coexisyst/files/iw dev wlan0 scan");
                _scan_pkts_left = getRxPacketCount() - start_rxpkts;
                Log.d(TAG, "Finished Wifi scan");
            }
        }
    };
  ...
}

However, it seems like when an incoming message comes in, handleMessage() actually runs in the UI thread. I know this because runCommand() blocks for 5 seconds, and my UI ends up unresponsive for 5 seconds.

Why is handleMessage() not running on the non-UI thread? Is there some other preferred way of communication between the threads?

Upvotes: 3

Views: 2646

Answers (3)

Alex Gitelman
Alex Gitelman

Reputation: 24732

It runs on UI thread because, handler is executed always on the thread that created it. In this case it would be UI thread.

I think that in you case you don't really need handler. Instead, just have some flag or appropriate data structure in your WifiMon task. Set this flag and required parameters from whatever place you call your handler now (with appropriate guards, of course). If you want it to be executed in the same thread as the task itself, you must at some point interrupt doInBackground main logic anyway and at this point, just check your flag.

If you want another thread, just introduce a method to start it. For example:

protected class WifiMon extends AsyncTask<Context, Integer, String>
{ 
   public void startScan() {
      Thread t = new Thread() {
        public void run() {
          // Scan here and read/update properties of WifiMon 
        }
      };
      t.start();
   }
}

And instead of

wifimon._handler.post(...);

use

wifimon.startScan();

Upvotes: 0

Ron
Ron

Reputation: 24235

Create the handler object in doInBackground() method.
Or
You can put the handler in a separate thread if it is independent of the Aysnctask.

EDIT :

mHandlerThread = new HandlerThread("some_name");
mHandlerThread.start();

/* we need to wait to get the looper instance */
while(!mHandlerThread.isAlive()) {};  
mHandler = new Handler(mHandlerThread.getLooper(), null);

Upvotes: 2

Samuel
Samuel

Reputation: 9993

the following method works in UI thread

onProgressUpdate

or you can create an interface and register for events

Upvotes: 0

Related Questions