背景
这个应用程序是一个简单的Wifi管理器,收集/扫描并在列表视图中显示结果。由于此扫描按间隔扫描,因此我创建了一个线程并在扫描之间设置了Thread.sleep(间隔),因此在处理完成后,它会休眠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并添加了一个只访问UI的方法RunOnUITHD(Runnable r)
用基本代码更新。
新主题代码:
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)并且我不在乎,我不知道我做错了什么。
更新
我记录了主线程代码的每一部分,它按预期运行,循环和休眠,但UI没有更新...
将记录代码添加到new Runnable()
我注意到以下内容:
向ThreadCounter添加一个断点,例如ThreadCounter==11
应该导致10"更新线程......"和"完成更新......"循环,如下面的代码所示。
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,所有进一步的测试都会导致1个记录的更新setText循环。
由于此线程是通过checkPermissions()
中@Override onStart()
的自定义方法启动的,因此我会显示一个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 Message显示(不会消失)并且setText在1循环上更新,这意味着threadRefresh
TextView包含以下文本:&#34; #Rereshed Times:1&#34; < / p>
答案 0 :(得分:1)
原来我没有死锁,这是由于Intents
选择不当。
<强>原因:强>
我使用的是Intent
。这创建了一个创建PendingIntent
的服务(用于点击通知以重新打开应用程序),这锁定了我的UI线程。因此,我上面的代码中没有任何内容影响/导致问题!
我是如何解决的:
使用日志。不是自定义日志,只是简单的Log.i()
我记录了我的代码的每一部分:
从高层开始,并找到可能的原因。
如果这不起作用/产生结果,看看你是否有其他类,在我的例子中是一个ServiceClass,记录它。
这是我发现我的代码没有进一步执行的地方,所以回溯到调用代码,我发现我使用了一个等待意图完成的Intent,然后继续前进,从而导致我的代码挂起。
<强>解决方案:强>
应该使用的是用于服务的两种意图类型之一。
这些是经常被询问和记录良好的对象。关于这两种意图类型之间的差异,StackOverflow有很多问题,here和here是2个排名很高的问题,还有一点UI and service Question
我将使用IntentService。
希望这有帮助!