K C
K C

Reputation: 219

Thread.join - Main thread won't resume execution

I'm facing this issue. I want my main thread to resume its execution only when other threads complete their execution. But my main thread is not executing even if other threads have done with their execution.

My code is as below:

public class MainActivity extends ActionBarActivity {
    private TextView mTextView;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       mTextView = (TextView) findViewById(R.id.text_test);

       TestLocalHost th = new TestLocalHost();
       Thread exe = new Thread(th);
       exe.start();

       try {
          exe.join();
       } 
       catch (InterruptedException e){
        e.printStackTrace();
       }

       mTextView.setText("MainThread");
}

private class TestLocalHost implements Runnable {

    @Override
    public void run() {

        final String s = JSONParser.doGet("http://<My system ip>/GetResult.ashx?op=getInfo",null);
        runOnUiThread(new Runnable() {
            @Override
            public void run() 
            {
                mTextView.setText(s);

             }
            });
        }
    }
}

I'm setting the value of mTextView with a value from exe thread. I need my main thread overwrite the mTextView with "Main thread" after it executes. I used a join() function to exe thread which will ensures main thread will wait till this thread completes execution. But once this thread completes exectuion my main thread is not writing into mTextView. What mistake am I doing?

Upvotes: 2

Views: 570

Answers (3)

njzk2
njzk2

Reputation: 39406

This has to do with how runOnUiThread works.

In android, the main thread has a Looper. That Looper holds a queue of runnable to run, one at a time.

When you call runOnUiThread, the Runnable is enqueued to the looper, meaning it will be executed after the current thing being run by the looper is done, and the queue is empty.

In your case, the Looper is executing onCreate when you call join. That means that your runOnUiThread will be enqueued for after that.

In terms of sequencing, that means that the following order of calls issue:

  • onCreate
  • start
  • doGet
  • runOnUiThread (end of thread)
  • setText (in onCreate) (end of onCreate)
  • setText (in runOnUiThread)

Upvotes: 3

Onik
Onik

Reputation: 19969

The reason for the "main thread not writing into mTextView" is that Thread exe terminates earlier than the one started by the runOnUiThread() method. And since join() waits only for Thread exe to finish (not the other one), you appearentely get "MainThread" of mTextView overwritten with String s set on the other thread.

You can check it by, for example, seeing Log:

...
mTextView.setText("MainThread");
Log.d("THREAD", mTextView.getText().toString());

Upvotes: 1

Shivam Verma
Shivam Verma

Reputation: 8023

Try using AsyncTask. It is meant for exactly this purpose.

private class GetDataFromNetwork extends AsyncTask<URL, Integer, Long> {
 protected Long doInBackground(URL... urls) {
     int count = urls.length;
     long totalSize = 0;
     for (int i = 0; i < count; i++) {
         //Get Data using url
     }
     return totalSize;
 }

 protected void onProgressUpdate(Integer... progress) {
     setProgressPercent(progress[0]);
 }

 protected void onPostExecute(Long result) {
     //Update UI Here. This runs on the UI Thread. 

 }
}

Upvotes: -2

Related Questions