与AsyncTask线程通信?处理程序不工作?

发布于 2024-12-01 17:58:22 字数 1168 浏览 2 评论 0原文

我有我的主 UI,并且有一个正在运行的 AsyncTask。我想与 AsyncTask 通信,让它在非 UI 线程上运行一些东西。所以我尝试做的是:

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() 实际上在 UI 线程中运行。我知道这一点是因为 runCommand() 阻塞了 5 秒,而我的 UI 最终没有响应 5 秒。

为什么handleMessage() 不在非UI 线程上运行?线程之间还有其他首选的通信方式吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

往日情怀 2024-12-08 17:58:22

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

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);
鸩远一方 2024-12-08 17:58:22

以下方法适用于 UI 线程

onProgressUpdate

,或者您可以创建一个界面并注册事件

the following method works in UI thread

onProgressUpdate

or you can create an interface and register for events

情仇皆在手 2024-12-08 17:58:22

它在 UI 线程上运行,因为处理程序始终在创建它的线程上执行。在本例中,它将是 UI 线程。

我认为在你的情况下你并不真正需要处理程序。相反,只需在 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();

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文