0

I created a chain of server-related operations and put them in a class called

OutgoingSync.java

I havent wrapped any threading around any of the network operations.

This is how I start the whole thing.

ExecutorService executorService = Executors.newFixedThreadPool(1);
                executorService.submit(new Runnable() {

                    @Override
                    public void run() {
                        new OutgoingSync(context);

                    }
                });

I am using ExecutorService because I want it to shutdown the threads for me, so I dont have to worry about that.

However, when the first network operation starts, I get a NetworkOnMainThread exception.

Here is a code snippet:

public class OutoingSync {

    public OutgoingSync(Context context){

        Log.e("OutgoingSync thread", Thread.currentThread.getName()); // Output "pool-2,thread-1"
        doSomeStuff();
    }

    private void doSomeStuff() {
        new UploadPhotosToServer();
    }

}

public class UploadPhotosToServer {
    public UploadPhotosToServer() {
        Log.e("Upload photos thread", Thread.currentThread.getName()); // Output is "main"
// And the following network-related code throws a NetworkOnMainThreadException (because it is run on the main thread)
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Kaloyan Roussev
  • 14,515
  • 21
  • 98
  • 180
  • Please post the entire stack trace, and supply relevant code snippets for where that stack trace refers to your app's code. – CommonsWare May 31 '15 at 12:45
  • edited with code snippet – Kaloyan Roussev May 31 '15 at 13:06
  • You are not getting a `NetworkOnMainThreadException` from that code snippet. – CommonsWare May 31 '15 at 13:11
  • That exception comes in UploadPhotosToServer, and as we can already see, the thread it runs in is the main thread. So the problem comes before that... Why is it run from the main thread is basically the problem here – Kaloyan Roussev May 31 '15 at 13:14
  • Well, since your code in your snippet will not even compile (there is no `currentThread` field on `Thread`, the class name is misspelled, etc.), it would appear that you never even ran that code. [When I run that code](https://gist.github.com/commonsguy/729d6355091158840c40), with appropriate corrections, I get both LogCat messages showing `pool-1-thread-1`. You might consider posting the **actual** stack trace and your **actual** code. – CommonsWare May 31 '15 at 13:27
  • It is a huge piece of code and it will take me an hour to change it in a way that I can post here. The question is am I missing something, maybe setting a thread policy or something else, that causes the newly created class from within the OutoingSync, to be run on the main thread instead of the same thread that OutgoingSync runs in. There is nothing in between both classes that does anything thread-related. – Kaloyan Roussev May 31 '15 at 13:29
  • "There is nothing in between both classes that does anything thread-related" -- presumably, there actually is, though it may be obscured by some API that you're calling, one that is doing thread shenanigans under the covers. However, it is difficult, if not impossible, to help developers who cannot supply [a minimal, complete, and verifiable example](http://stackoverflow.com/help/mcve) of the problem, or at minimum, the stack trace that is actual evidence of the problem. – CommonsWare May 31 '15 at 13:32
  • Okay I will try to post a minimum code example that is verifiable and complete – Kaloyan Roussev May 31 '15 at 13:34
  • You were absolutely right! One of the 10 classes that I had to rewrite to stop using asynctask, had remained an asynctask and it switched the sequence to the mainthread by calling onpostexecute! So there was nothing wrong in the way I started this operation, but an asynctask I had overlooked did the switch to the main thread, and the rest of the sequence continuted running there. – Kaloyan Roussev May 31 '15 at 14:57
  • 1
    And, to hammer home the point, had you posted the stack trace, we would have seen the `onPostExecute()` call in that trace, and you would have had your answer two hours ago. That being said, I am glad that it is working for you now. – CommonsWare May 31 '15 at 15:02
  • It was also very useful for me to find out that TID in LogCat stands for Thread ID and I noticed the exact point where TID switched back to be equal to PID (I have log calls in every method) – Kaloyan Roussev May 31 '15 at 15:04

2 Answers2

0

From the documentation

The exception that is thrown when an application attempts to perform a networking operation on its main thread

So, you can try running the code in AsyncTask . Its executeOnExecutor() method can do the trick.

http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor(java.util.concurrent.Executor, Params...)

Sarit Adhikari
  • 1,344
  • 2
  • 16
  • 28
0

The issue that you used submit method and not execute. Therefore you are still on the main thread.

submit

Submits a Runnable task for execution and returns a Future representing that task. The Future's get method will return the given result upon successful completion.

execute

Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation.

from [ExecuterService](http://developer.android.com/reference/java/util/concurrent/ExecutorService.html#submit(java.lang.Runnable, T)) and Executer

EE66
  • 4,601
  • 1
  • 17
  • 20