gpt4 book ai didi

java - ANR 代码在单独的线程上运行

转载 作者:行者123 更新时间:2023-11-30 10:42:26 24 4
gpt4 key购买 nike

背景:

这个应用程序是一个简单的 Wifi 管理器,收集/扫描并在 ListView 中显示结果。由于此扫描按间隔进行扫描,因此我创建了一个线程并在扫描之间设置了 Thread.sleep(interval),因此在处理完成后,它会 hibernate X 毫秒。

我对我的代码进行了一些“更改”/更新,现在我的应用程序进入 ANR 状态并显示一条调试器消息 "Signal Catcher"]: reacting to signal 3

完整错误:

07-01 10:14:16.772 10027-10034/com.cynetstudios.wifimanager I/art: Thread[2,tid=10034,WaitingInMainSignalCatcherLoop,Thread*=0xa9007000,peer=0x12d1a0a0,"Signal Catcher"]: reacting to signal 3
07-01 10:14:17.101 10027-10034/com.cynetstudios.wifimanager I/art: Wrote stack traces to '/data/anr/traces.txt'

问题:

添加权限前:

在 main 的 onCreate() 中,我有我的代码来启动我的扫描循环并开始输出数据,这有效并按预期输出数据。

线程代码:

    t = new Thread(new Runnable() {
public void run() {
while (!bStopThread) {
ThreadCounter++;

if (bSafe) {
initWiFiArrays(); //Scans and inserts data into lists
CreateSetAdapter(); //Converts lists into adapter, and sets adapter to ExpandableListView
threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
writeResultsToFile(); //Write results to file
} else
stopScan();

try {
Thread.sleep(scanInterval);
} catch (Exception x) {
x.printStackTrace();
}
}
}
});
t.start();

添加权限后:

经过一些研究,我发现我应该从 onCreate 中删除这个 Initiate scan 方法,因为它会阻止任何线程调用,我将它添加到 onStart 并添加了一个方法 RunOnUITHD(Runnable r ) 它将仅访问 UI 以使用基本代码进行更新。

新线程代码:

     t = new Thread(new Runnable() {
public void run() {
while (!bStopThread) {
ThreadCounter++;

if (bSafe) {
initWiFiArrays();
CreateSetAdapter();
RunOnUITHD(new Runnable() {
@Override
public void run() {
threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
}
});
writeResultsToFile();
} else
stopScan();

try {
Thread.sleep(scanInterval);
} catch (Exception x) {
x.printStackTrace();
}
}
}
});
t.start();

处理程序定义为:handler = new Handler(context.getMainLooper());

RunOnUITHD

private void RunOnUITHD(Runnable runnable) {
handler.post(runnable);
}

我仍然收到 ANR ( latest ANR Traces ) 并且我不明白,我不知道我做错了什么。

更新:

我记录了主线程代码的每一部分,它按预期运行,循环和 hibernate ,但 UI 没有更新...

将日志记录代码添加到 new Runnable() 我注意到以下内容:

为例如 ThreadCounter 添加一个断点ThreadCounter==11 应该会产生 10 个“Updaing Thread...”和“Finished update...”循环,如下面的代码所示。

RunOnUITHD(new Runnable() {
@Override
public void run() {
logm("POST HANDLER: updating Thread Refresh Text");
threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
logm("POST HANDLER: Finished update Thread Refresh Text");
}
});

相反,我只注意到日志中显示的 4 个循环。

运行进一步的测试,ThreadCounter==3,循环记录 = 1,所有进一步的测试导致更新 setText 的 1 个记录循环。

由于此线程是通过我的 @Override onStart() 中的自定义方法 checkPermissions() 启动的,因此我显示了一条 toast 消息,然后是 checkPermissions

@Override
protected void onStart() {
super.onStart();
Toast.makeText(main.this, "Starting Service", Toast.LENGTH_SHORT).show();
logm("checking permissions in 'onStart'");
checkPermissions();
}

尽管进行了这些测试,但 Toast 消息显示(不会消失)并且 setText 在 1 个循环中更新,这意味着 threadRefresh TextView 包含以下文本:“# Refreshed Times : 1”

最佳答案

事实证明我没有死锁,这是由于 Intents 的选择不当造成的。

原因:

我使用的是一个Intent。这创建了一个创建 PendingIntent 的服务(用于点击通知以重新打开应用程序),这锁定了我的 UI 线程。所以我上面的代码中没有任何内容影响/导致问题!

我是如何解决这个问题的:

使用日志。不是自定义日志,只是简单的 Log.i()

我记录了我的代码的每一部分:

  1. 从高层次入手,深入研究可能的原因。

  2. 如果这不起作用/产生结果,请查看您是否有任何其他类,在我的例子中是 ServiceClass,记录它。

这是我发现我的代码没有进一步执行的地方,所以回溯到调用代码,我发现我使用了一个 Intent,它在继续之前等待 Intent 完成,从而导致我的代码挂起。

解决方案:

应该使用的是用于服务的 2 种 Intent 之一。

这些是经常被问及且有据可查的对象。关于这两种 Intent 类型之间的区别,StackOverflow 上有很多问题,herehere是 2 个排名靠前的问题,还有一点 UI and service Question

我将使用 IntentService。

希望这对您有所帮助!

关于java - ANR 代码在单独的线程上运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38140787/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com