связь с потоком AsyncTask? Обработчик не работает? - PullRequest
3 голосов
/ 29 августа 2011

У меня есть основной интерфейс, и у меня запущен AsyncTask. Я хочу связаться с AsyncTask, чтобы он выполнял что-то в потоке, не являющемся пользовательским интерфейсом. Итак, я попытался сделать следующее:

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");
            }
        }
    };
  ...
}

Однако, похоже, что при поступлении входящего сообщения handleMessage () фактически выполняется в потоке пользовательского интерфейса. Я знаю это, потому что runCommand () блокируется на 5 секунд, а мой пользовательский интерфейс перестает отвечать на запросы в течение 5 секунд.

Почему handleMessage () не работает в потоке без пользовательского интерфейса? Есть ли какой-то другой предпочтительный способ связи между потоками?

Ответы [ 3 ]

2 голосов
/ 29 августа 2011

Создать объект обработчика в методе doInBackground().
Или
Вы можете поместить обработчик в отдельный поток, если он не зависит от Aysnctask.

РЕДАКТИРОВАТЬ:

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);
0 голосов
/ 29 августа 2011

Он выполняется в потоке пользовательского интерфейса, потому что обработчик всегда выполняется в потоке, который его создал. В этом случае это будет поток пользовательского интерфейса.

Я думаю, что в вашем случае вам не нужен обработчик. Вместо этого просто укажите флаг или соответствующую структуру данных в своей задаче WifiMon. Установите этот флаг и необходимые параметры из любого места, которое вы сейчас называете своим обработчиком (с соответствующими охранниками, конечно). Если вы хотите, чтобы он выполнялся в том же потоке, что и сама задача, вы все равно должны в какой-то момент прервать doInBackground основную логику, и на этом этапе просто проверьте свой флаг.

Если вам нужен другой поток, просто введите метод для его запуска. Например:

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

И вместо

wifimon._handler.post(...);

использование

wifimon.startScan();
0 голосов
/ 29 августа 2011

следующий метод работает в потоке пользовательского интерфейса

onProgressUpdate

или вы можете создать интерфейс и зарегистрироваться для событий

...