2

I have two functions which does SOAP calls and another function which makes a List from both the SOAP calls. I am figuring how to wait for the two SOAP calls to finish and run the third function.

Function A = SOAP (independent of B)
Function B = SOAP (independent of A)
Function C = Making a List from A & B (dependent on both A & B)
Function D = displaying using List from C

My current solution is putting A in an asynctask, B in the A's onpostexecute, and C in B's onpostexecute which is NOT working. I tried putting two logs in every function, at the start and at the end of each function. It started logging B's function before A has finished its' two logs which in result mess up C.

I am thinking of putting A & B in separate threads and joining them once they are done. Then putting C in async task or another thread. But I am afraid that will cause issue with D (displaying the list from C) because of racing problem using my current solution with async task.

Jack Smother
  • 207
  • 1
  • 8
  • 32

2 Answers2

2

Well, it's a question of logical order and concurrency. Try this way :

public void process() {
        Thread funcAThread = new Thread(new Runnable() {
            @Override
            public void run() {
                startFunctionA();
            }
        });

        Thread funcBThread = new Thread(new Runnable() {
            @Override
            public void run() {
                startFunctionB();
            }
        });

        try {
            funcAThread.start();
            funcBThread.start();
            funcAThread.join();
            funcBThread.join();
            startFunctionC();
            startFunctionD();
        } catch (InterruptedException e) {
            Log.getStackTraceString(e);
        }
    }

Note: make sure that all call to UI Views (especially in function D) are processed inside the UI Thread using Activity.runOnUiThread(Runnable runnable).

Note 2: if functionC is time-consuming, you may call it from a Thread as well so that it keeps your app responsive (which is very important). So based on my code above :

    try {
        funcAThread.start();
        funcBThread.start();
        funcAThread.join();
        funcBThread.join();
        new Thread(new Runnable() {
            @Override
            public void run() {
                startFunctionC();
                //once completed, call UI thread for D !
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        startFunctionD();
                    }
                });
            }
        }).start();
    } catch (InterruptedException e) {
        Log.getStackTraceString(e);
    }

Note 3: I would not recommand the usage of AsyncTask. Not because it's bad (certainly not) but because they are intended for operations where you need to define a beginning, a long operations to be processed in the background with regular updates performed on the UI thread and finally some other operations to be performed once the main long operations are completed. You can use one AsyncTask to perform everything but you would loose the advantage of using two concurrent threads that can take advantage of multi-core CPUs and therefore process your data / perform your operations much faster. Furthermore, I believe on some Android version, you can only use one AsyncTask at the time. Check this answer for more informations : https://stackoverflow.com/a/4072832/3535408. So you are better off with threads : clearer, simplier and just as fast.

Community
  • 1
  • 1
Mackovich
  • 3,319
  • 6
  • 35
  • 73
  • For what it is worth, AsyncTasks can run in parallel. Using `task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);`. That is however locked to later Android versions. – Knossos Jan 13 '16 at 12:23
  • @Knossos that is entirely correct, this is why I included a link in my **Note3** that provide a lot of details regarding the problematic of running parrallel AsynTasks ;-) – Mackovich Jan 13 '16 at 12:27
  • Oops! Missed that. My apologies! – Knossos Jan 13 '16 at 12:29
  • 1
    No problem. It's funny I ran into this SO post, because I had the same problem one year ago as I was trying to run 5 AsyncTask at the same time. I hate AsyncTask and I try not to use them as much as possible. Custom managed ThreadPool with fixed number of threads based on number of available cores is the way to go as long as you now what to do ;-) – Mackovich Jan 13 '16 at 12:32
  • I was under the impression that asyntasks can once again be run simultaneously in parallel? If so then several asynctasks can be run and can all synchronise if used in conjunction with a countdown latch? – Mark Jan 13 '16 at 12:41
2

Run A & B at the same time via their separate AsyncTask.

In the onPostExecute function of A & B, call a function that records that the task had run.

In this callback function, you check whether both A & B have completed, and then run C in another AsyncTask.

Example:

In each AsyncTask:

onPostExecute(Void result) {
    mCallback.onTaskCompleted(this.class);
}

In your class that calls your AsyncTasks:

onTaskCompleted(Class task) {
    if(task instanceof AsyncTaskA) mTaskA = true;
    else if(task instanceof AsyncTaskB) mTaskB = true;

    if(mTaskA && mTaskB) {
        runTaskC();
    }
}
Knossos
  • 15,802
  • 10
  • 54
  • 91