I need to use threads in my android application because I am doing image processing w/ native opencv. Here is my code:
void Detector::processBinary(Mat &binary) {
//do stuff
}
void Detector::Detect() {
...
thread t1(processBinary, binary);
t1.join();
}
However, I get the error "invalid use of non-static member function" from thread t1(processBinary, binary) whenever I try to run the app. This line, however, works perfectly in visual studio. Can anyone help me with this? Thanks in advance!
You use member function, that needs this argument (it must be called on some object). There are two alternatives:
Use static class function (or non-class function at all):
void processBinary(Mat &binary) {
//do stuff
}
void Detector::Detect() {
...
thread t1(processBinary, binary);
t1.join();
}
Or pass proper arguments if we want utilize member function:
void Detector::processBinary(Mat &binary) {
//do stuff
}
void Detector::Detect() {
...
thread t1(&Detector::processBinary, *this, binary);
t1.join();
}
Related
I have some Android app that should load some data on start and process it as soon as possible. For better performance data processing done in native code.
But in some time data amount was increased and it becomes to block UI while processing. The weird thing is that I launch JNI call from background thread and I believe native code should also work in background.
So few questions:
how to detect is native code works in main thread?
how to detect who blocks UI?
Some code sample:
// java
new Thread(new Runnable() {
#Override
public void run() {
ResourceLoader.loadListsAndParse(); // native call
}
}).start();
// c++
void RulesManager::loadRules() {
if (!rules_loaded_) {
using namespace std;
base::FilePath my_dir;
GetCacheDirectory(&my_dir);
this->loadRulesInternal(my_dir, true);
}
}
void RulesManager::loadRulesInternal(base::FilePath& path, bool processExceptions) {
base::FileEnumerator files(path, false, base::FileEnumerator::FILES);
for (base::FilePath name = files.Next(); !name.empty(); name = files.Next()) {
this->loadRulesFromFile(name.AsUTF8Unsafe(), processExceptions);
}
}
bool RulesManager::loadRulesFromFile(const std::string& filePath, bool processException) {
bool result = false;
std::ifstream file(filePath);
std::string str;
while (std::getline(file, str)) {
result = this->addRule(str, processException);
}
return result;
}
Android has system calls getpid() and gettid() defined in <unistd.h>. If the pid_t return values are equal, then your native code runs on the UI thread.
I use BlockCanary for that purposes. If you know about LeakCanary, BlockCanary provides reports about UI blocking in the same way.
How to detect is native code works in main thread?
You can apply Log method inside your code.
For example your code is:
if(myInt > 0){
doSth();
}
Insert Log method;
if(myInt > 0){
doSth();
Log.i("Info", "if statement is true.");
}
now your device will type to the console if your if statement runs. So in your thread, you can insert Log method to critical lines to see if it is running or not.
how to detect who blocks UI?
As in my first answer, again you can see it from the console if you implement Log methods to your code.
But if you want to do it properly, I suggest you to check Asynctask. This will take time to learn how to implement it properly but the most practical way to pass the long jobs to background in Android is Asynctask.
To explain what I want to achieve I wrote what I'm able to do and then - when a problem appears. What works well:
1) I have webView1 containing in loaded HTML
<button onclick="android.buttonPressed();">Click</button>
binded with interface:
private class WebAppInterface1 {
Context context;
WebAppInterface1(Context c) {
context = c;
}
#JavascriptInterface
public void buttonPressed() {
Toast.makeText(context, "buttonPressed", Toast.LENGTH_LONG).show();
}
}
The HTML button works.
2) I have webView2 containing in loaded HTML
<script>
function f() {
document.write("bla bla bla");
}
</script>
Then I call
webView2.loadUrl("javascript:f();");
in android code and it works too.
Now I want to modify webView2's page by pressing button in webView1. Technically it means that I want to call f() inside webView2 when JS interface detected click in webView1. So I add this line
webView2.loadUrl("javascript:f();");
in buttonPressed() function inside JS interface. But it has no effect. What can cause the problem? Are there any limitations in connecting these reciever and sender? Maybe I missed some settings or permissions?
There are my project files, I tried to make them as simple as possible: layout, html, java. Didn't edit other files. Can give any additional information if needed.
I understood that my problem is related to another problem: one can't update UI from non-main thread (was covered on SO here and here). But in my case there isn't any errors for some reason. Maybe because of JavaScript isn't as "strict" as Java.
So solved by adding android.os.Handler in my activity class, assigning it in onCreate function:
handler = new Handler() {
public void handleMessage(Message msg) {
webView2.loadUrl("javascript:f()");
}
}
and accessing it in buttonPressed function:
handler.obtainMessage(1).sendToTarget();
P.S. Another way is to wrap calling webView2.loadUrl("javascript:f()"); by Runnable and calling runOnUiThread(runnable). It looks more neat:
webView1.addJavascriptInterface(new Object() {
#JavascriptInterface
public void buttonPressed() {
runOnUiThread(new Runnable() {
#Override
public void run() {
webView2.loadUrl("javascript:f()");
}
});
}
}, "android");
P.P.S. Enabling Java 8 in app/build.gradle allows to write it even more neat:
runOnUiThread(()->{webView2.loadUrl("javascript:f()");});
I've found the following code does not work because the while loop steals the lock indefinitely:
public void run()
{
while(true)
{
synchronized(run)
{
if (!run) break;
[code]
}
}
}
public void stopRunning()
{
synchronized(run)
{
run = false;
}
}
My goal is to ensure that I don't return from a stopRunning() command until I know that my run() function is no longer actually running. I'm trying to prevent the run function from continuing to reference other things that I'm in the process of destroying. My first thought then is to add a line of code such as Thread.sleep(100) prior to synchronized(run) in order to ensure that it releases the lock. Is this the recommended practice or am I overlooking something [stupid/obvious]?
Thanks!
If you just need stopRunning() to block until run() finishes doing stuff, you could just use a CountDownLatch set to 1. Call it stoppedSignal or something, and in run() you can call stoppedSignal.countDown() when it is finished. In stopRunning you can then set your condition for run() to finish and then call stoppedSignal.await(). It won't proceed until run() "releases" the latch by counting down. This is just one way to do it that would be a bit neater. All the synchronized block stuff that be got rid of.
Beware of the "synchronized" keyword - it's a very blunt and old tool. There are some wonderful things in the concurrency package that fulfil specific purposes much more neatly. "Concurrency In Practice" is a fantastic book on it.
Would something like this suffice?
public void run()
{
while(run)
{
[code]
}
onRunStopped();
}
public void stopRunning()
{
run = false;
}
public void onRunStopped()
{
// Cleanup
}
while synchronized(run) will lock run, you can use run.wait() to freeze the thread run() is executed in.
in another thread, use run.notify() or run.notifyAll() to get run() to continue.
synchronized is used to sync between threads. use it only if there is a potential race condition between 2 or more of them.
Ensure the 'run' object is the same from both point in the code.
The while loop should be synchronizing to the same object as the stopRunning() method.
The while loop is not hogging the lock, it is more likely that the two pieces of code could be referencing a different object. But I cannot tell because the run object is not shown in the code.
There are probably more elegant solutions, but I believe you could solve it with the changes bellow:
private boolean lock;
public void run()
{
while(true)
{
synchronized(lock)
{
if (!run) break;
[code]
}
}
}
public void stopRunning()
{
run = false;
synchronized(lock){ }
}
I have written some database queries in synchronized method. Ideally if some code is executing inside this code block then other thread should not access this but it does sometimes in my case.
synchronized private void func1 () {
// printing some log for start
// some database code
// printing log at the end
}
So the log which i have printed at the start prints twice. How to block this thing?
The synchronized block uses a lock on the object that calls func1(). If you call func1 from different threads using different objects the situation encountered is possible.
Assuming you have
class A {
synchronized private void func1() {}
void func2() { func1()}
}
And call from 2 different threads new A().func2(), func1() is not thread safe in this case.
If you have only 1 instance of class A in my example than it must work.
I'm trying to use the HandlerThread class to manage thread in my application. The following code is working great :
public class ThreadA extends HandlerThread
{
private void foo()
{
//do something
}
private void bar()
{
//Do something else
}
#Override
public boolean handleMessage(Message msg) {
switch(msg.what)
{
case 1:
{
this.foo();
break;
}
case 2:
{
this.bar();
break;
}
}
return false;
}
#Override
protected void onLooperPrepared()
{
super.onLooperPrepared();
synchronized (this) {
this.AHandler = new Handler(getLooper(),this);
notifyAll();
}
}
}
1- Should i override the run() method ? In a "classic" thread most of the code is located in the run method.
2- Lets imagine i need my foo() method to be a infinite process (getting a video streaming for example).
What's the best solution ?
Overriding run with my foo() code ?
Simply adding a sleep(xxx) in foo() :
private void foo()
{
//do something
sleep(100);
foo();
}
-Using a delayed message like :
private void foo()
{
//do something
handler.sendEmptyMessageDelayed(1,100);
}
PS : Asynctask will not cover my need , so do not bother to tell me to use it.
Thanks
I think you didn't get the idea of HandlerThread. HandlerThread is designed to implement thread that handles messages. What this means is that it uses Looper.loop() in its run() method (and that's why you shouldn't override it). This in turn means that you don't need to sleep in onHandleMessage() in order to prevent thread from exiting, as Looper.loop() already takes care of this.
To summarize:
No, do not override run().
You don't need to do anything to keep thread alive.
If you want to learn/undestand more about HandlerThread, read about Looper and Handler classes.
You shouldn't override the run method in the HandlerThread since that is where the core functionality of the class actually occurs. Based on what you are showing, I also see no reason to do so.
If your task itself is infinite, there isn't anything preventing you from having it execute that way. The only reason you might want to use handler.sendEmptyMessageDelayed is if you plan to have other tasks that you want run queued on the HandlerThread while foo() is executing. The other approach you recommended will prevent the HandlerThread from handling any other message. That being said, I suspect there is a better way to make your task infinite.
Finally, you should remember to stop your infinite task and call HandlerThread.getLooper().quit() to make sure your HandlerThread stops nicely.