Unity Networking – Async vs Coroutine

Few days ago I was writing some replay on one of the forums regarding Unity networking and had to provide 2 examples of network access with native Unity Coroutine functionality and basic C# functionality which also work great inside the Unity, that thread was killed by moderators for the unrelated spam, however I still have Unity project as example, so ill re-share it here.

First of all lets have a look at the difference of Async and Coroutines:

Coroutines: in simple words could be explained as reference to the execution point where process keep coming back to check if condition was satisfied.
Example:
Lets assume we have to register new user in our server side database from Unity application.
Then we will have to:

  • Gather data from input fields
  • Validate data
  • Build up GET request URL or POST object
  • Send data to the server
  • Wait for server response

Where at the server side we will also have to perform several steps, like:

  • Capture client request
  • Validate input
  • Check database if user not already registered
  • Register user
  • Buildup response to client
  • Respond

So we talking about good few seconds delay between send request to server and receive response from it.
In case of Coroutines, process will send the data to server and make reference at that point, it would continue execution of the following code without blocking state, however it will keep coming back to that reference mark to check if execution of coroutine was complete and condition was satisfied. In other words execution process jumping from currently executed code to coroutine point and back, until coroutine will be completed.
Asynchronous: is on other had completely separate thread, which runs on background individually and usually notify when it is complete through call back method.

Now lets look on the Actual Unity implementation of Coroutines:

Execution class:

public class GUI : MonoBehaviour {

    //skipped

    void Start () {
        coroutineUrl =  "https://dl.dropboxusercontent.com/u/15715229/Habra/coroutine.html";
       //skipped
    }

    void OnGUI()
    {
        //skipped
        if(GUILayout.Button("Coroutine Example"))
        {
             //skipped
             StartCoroutine(CoroutineExample.CoroutineWebRequest(coroutineUrl));
             //skipped
        }
        //skipped
    }
}

We just hit the button and it call CoroutineExample.CoroutineWebRequest, lets see what is going on there
Process Class:

public class CoroutineExample : MonoBehaviour {

    private static string serverResponse;

    public static IEnumerator CoroutineWebRequest(string url)
    {
        WWW web = new WWW(url);
        while (!web.isDone)
        {
            yield return null;
        }

        if (web.error != null)
        {
            serverResponse = "Server Error: " + web.error;
        }
        else
        {
            serverResponse = "Coroutine Server Say: " + web.text;
        }
    }
}

As you see it is very simple, it will yield – or wait by executing another code until process is done and while statement is complete and then continue execution from that point.

Now lets have a look at the Async example:

I will start from Async worker – it is the actual class where we perform web access:

using System.Net;

public class AsyncWorker {

	public string DoWork(string url)
    {
        WebClient web = new WebClient();
        string result = web.DownloadString(url);
        return "Async Server Say: "+result;
    }
}

Because we accessing web in asynchronous way we are blocked from using Unity native WWW class. Unity allow to use WWW class only from main thread however Async process is parallel thread. (Keep in mind that there are good few classes which unity doesn’t allow to run in parallel thread)
It is not a problem as we can use C# native WebClient Class which from my point of view even better than Unity WWW

Now lets look how we start Async request from GUI button click:

public class GUI : MonoBehaviour {

	//Skipped

	void Start () {
        asyncUrl =      "https://dl.dropboxusercontent.com/u/15715229/Habra/async.html";
		//Skipped
	}
	
    void OnGUI()
    {
		//Skipped
		if (GUILayout.Button("Async Example"))
		{
			//Skipped
			AsyncExample.StartAsync(asyncUrl);
			//Skipped
		}
		//Skipped
    }
	//Skipped
}

And finally lets have a look on what is going on in the misterious AsyncExample.StartAsync method:

using System;
using System.Runtime.Remoting.Messaging;
using UnityEngine;

public class AsyncExample : MonoBehaviour {

    private static string serverResponse;
    private delegate string myCallBackDelegate(string url);

    public AsyncExample()
    {
        serverResponse = ""; 
    }
	
    public static void StartAsync(string url)
    {
        myCallBackDelegate deleg = new myCallBackDelegate(new AsyncWorker().DoWork);
        deleg.BeginInvoke(url, new AsyncCallback(onServerResponse), null);
    }


    private static void onServerResponse(IAsyncResult result)
    {
        AsyncResult res = (AsyncResult)result;
        myCallBackDelegate deleg = (myCallBackDelegate)res.AsyncDelegate;
        serverResponse = deleg.EndInvoke(result);        
    }
}

It is exactly the same Async process which I already describe in one of my previous post
It just create delegate, BegineEnvoke it by passing input parameters which is URL in our case and set CallBack method where Server response supposed to fall when completed for extraction of an actual response.
That is it!

Full Unity project can be downloaded from my:

Java Advanced Async Future

In my previous publication I showed example of C# parallel calculation where we assign task to the background thread and tell it which method to call when completed. There is one big advantage in C# over Java is that C# can pass pointers to the method as parameters, what allowed us to pass callback method which suppose to be invoked when result is ready. Unfortunately in Java we could not pass entire method as parameter to call it later, however there is workaround which I will show you today.

Task:

Execute parallel task which will invoke specified method on completion and return parameters from calculations to it.

A bit of additional information:

We will approach this task from the real live example. lets assume we are in the office where working several departments. We are Department Nr1 preparing tasks for other departments – “Management department” or “Caller”. Once we generate new task we passed it to the desired department – “Worker” and willing to be notified when “Worker” complete job so we could assign new job to it. It would mean that somebody from “Workers” department would have to come in in our office – “Call back method” and tell us that “Workers” ready to take new task and here is result from previous task. So lets look on implementation of such idea.

Implementation:

I will start from launcher:

package launcher;

import caller.Caller;

public class Launcher {

	public static void main(String[] args) {

        new Caller();
    }

}

There is nothing to comment.
Next We will create interface:

package interfaces;

public interface CallBackInterface {

	public void OnCallBackMethod(String returnedResult);

}

This interface will contain just one method – that is the one which will be our callBack method
Now lets look at the implementation of “Worker”

package workers;

import java.util.Random;

public class SlowWorker {
	
	private int id;
	private int timeToSleep;
	public SlowWorker(int id)
	{
		this.id = id;
		timeToSleep = new Random().nextInt(5000) + 1000;
		
	}
	
	public String doWork()
	{
		try{
			Log("Worker ["+id+"] Starting Heavy Calculations");
			
            Thread.sleep(timeToSleep);
            int digit1 = new Random().nextInt(100);
            int digit2 = new Random().nextInt(100);
            int sum = digit1+digit2;
            
            Log("Worker ["+id+"] Finished after: "+timeToSleep);
            
            return "Worker: ["+id+"] Sum of "+digit1+" and "+digit2+" = "+sum;
		}
		catch(Exception e)
		{
			Log("I ["+id+"] was forcibly interrupted");
			return "Worker: ["+id+"] Crash: "+e;
		}
	}
	
	public void Log(String msg)
	{
		System.out.println(msg);
	}

}

Worker accept own unique ID in constructor, just for understanding who is who, also it define sleep time as random from 1 sec to 6 sec, so each worker will be busy random amount of time

In doWork() method – we just sleep – pretending to do more heavy calculations and sum up two randomly generated digits. once it is done we return answer as String.

Now lets look at another worker – thats the one who will run from his “Workers” department to our “Management Department” and notify us that job was complete and give us text reports 🙂

package workers;

import interfaces.CallBackInterface;

import java.util.concurrent.Callable;

public class NotifierWorker implements Callable<Object>{
	
	
	private CallBackInterface callBack;
	private int id;
	
	public NotifierWorker(int id)
	{
		this.id = id;
	}
	
	@Override
	public Object call() throws Exception {
		callBack.OnCallBackMethod(new SlowWorker(id).doWork());
		return null;
	}
	
	public void setCallBack(CallBackInterface callBack)
	{
		this.callBack = callBack;
	}
	
	public CallBackInterface setCallBack()
	{
		return callBack;
	}

}

This worker – “Notifier” implements Callable what automaticly generate call() method for us. that is where happens all the async calculations. however before we execute async calculation we have to set response method which is our Management office to specifically tell to Notifier worker where to find us – “Management” when his department would complete a job.

Lets have a look on that:

package caller;

import interfaces.CallBackInterface;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import workers.NotifierWorker;

public class Caller implements CallBackInterface{
	
	private boolean workerComplete;
	private int nrOfWorkersToRun;
	private int jobsComplete;
	private static int id;
	
	public Caller()
	{
		workerComplete = false;
		nrOfWorkersToRun = 5;
		jobsComplete = 0;
		id = 1;
		startExecution();
	}
	
	@Override
	public void OnCallBackMethod(String returnedResult) {
		Log("Main Thread - OnCallBack: "+returnedResult);
		jobsComplete++;
		
		if(jobsComplete == 5)
			workerComplete = true;
	}
	
	public void startExecution()
	{
		
        Log("Main Thread: Start Work @: "  + new java.util.Date());
        Log("");
        ExecutorService es = Executors.newFixedThreadPool(3);
        for(int i = 0; i < nrOfWorkersToRun; i++) {
        	int nr = getNextId();
        	Log("Main Thread: giving job to worker nr: ["+nr+"]");
	        NotifierWorker slaveNotifier = new NotifierWorker(nr);
	        slaveNotifier.setCallBack(this);
	        es.submit(slaveNotifier);
        }

        try
        {
        	while(!workerComplete)
        	{
        		Log("Main Thread: doing my own stuff.........");
        		Thread.sleep(800);
        	}
        }
        catch(Exception e)
        {
        	Log("Main Thread CRASHED: "+e);
        }
        
        Log("");
        Log("Main Thread: End work @: " + new java.util.Date());
        System.exit(0);
	}
	
	
	public int getNextId()
	{
		return id++;
	}
	
	public void Log(String msg)
	{
		System.out.println(msg);
	}

}

As any management department it is big, important and hard to follow what a hell is it doing. But we will try:
in two words – we just schedule 5 tasks to workers and wait until all of them complete and displaying result of each completion once it is ready. Also keep in mind that we have 5 tasks however we limit our workers to only 3 concurrent task at a time to save up on their salaries 🙂

1) ExecutorService es = Executors.newFixedThreadPool(3); – We create Threadpool with size of three – that will allow us to limit all background tasks to three in total at the same time. (it is not a requirement, just more fun and extra chance to demonstrate thread pool queue)
2) NotifierWorker slaveNotifier = new NotifierWorker(nr); – We create notifiers and assign unique ID to each of them:
3) slaveNotifier.setCallBack(this); – Tell to each notifier where he can find us when job complete
4) es.submit(slaveNotifier); – send him to work on the given task
5) once hes task is complete he will tell us about it in OnCallBackMethod method where we keep track of how many was completed out of executed.
6) once amount of completed tasks equal to amount of scheduled tasks we assume that this is over and exit.

and here is console output for you:

Main Thread: Start Work @: Fri Mar 14 15:47:29 GMT 2014

Main Thread: giving job to worker nr: [1]
Main Thread: giving job to worker nr: [2]
Worker [1] Starting Heavy Calculations
Main Thread: giving job to worker nr: [3]
Worker [2] Starting Heavy Calculations
Main Thread: giving job to worker nr: [4]
Worker [3] Starting Heavy Calculations
Main Thread: giving job to worker nr: [5]
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Worker [2] Finished after: 2941
Main Thread - OnCallBack: Worker: [2] Sum of 19 and 58 = 77
Worker [4] Starting Heavy Calculations
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Worker [3] Finished after: 4552
Main Thread - OnCallBack: Worker: [3] Sum of 80 and 68 = 148
Worker [5] Starting Heavy Calculations
Worker [1] Finished after: 4794
Main Thread - OnCallBack: Worker: [1] Sum of 51 and 71 = 122
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Worker [4] Finished after: 5656
Main Thread - OnCallBack: Worker: [4] Sum of 81 and 46 = 127
Main Thread: doing my own stuff.........
Main Thread: doing my own stuff.........
Worker [5] Finished after: 5444
Main Thread - OnCallBack: Worker: [5] Sum of 1 and 93 = 94

Main Thread: End work @: Fri Mar 14 15:47:39 GMT 2014

And as usually you can download entire project here:

C# Async Calculations

This is example of Async calculation implementation in C# which works nearly in the same way as recently published post related to Java Async Programming

Task:

Execute parallel task on background and retrieve result of calculations once task is complete.

Implementation:

Lets start from our worker which will perform heavy calculations

using System;
using System.Threading;

namespace AsyncCalculations
{
    class AsyncWorker
    {
        public string performLongAndHeavyCalculation(int dig1, int dig2)
        {
            Console.WriteLine("Worker: Starting job");
            int sum = dig1 + dig2;
            Thread.Sleep(3000);
            Console.WriteLine("Worker: Job Complete");
            return "Result of heavy calculation is: "+sum;
        }
    }
}

Well calculations are not that heavy 🙂
but 3 seconds of sleep could represent request to the server side database. There is nothing really to talk about, everything simple and straightforward.

Now lets have a look at our main thread – async caller:

using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;

namespace AsyncCalculations
{
    class AsyncCaller
    {
        public static void Main(string[] args)
        {
            new AsyncCaller();
        }

        //define delegate
        private delegate string MyAsyncDelegate(int dig1, int dig2);

        private bool gotResponse;
        private string workerResponse;
        public AsyncCaller()
        {
            gotResponse = false;
            int num1 = 10;
            int num2 = 30;

            Console.WriteLine("Main Thread: Start");
            Console.WriteLine("Main Thread: launching worker");
            //create delegate
            MyAsyncDelegate myDelegate = new MyAsyncDelegate(new AsyncWorker().performLongAndHeavyCalculation);
            //execute async task
            myDelegate.BeginInvoke(num1, num2, new AsyncCallback(onCallBack), null);
            Console.WriteLine("Main Thread: worker executed");

            //wait for a response
            while(!gotResponse)
            {
                Console.WriteLine("Wating for worker to complete his job....");
                Thread.Sleep(500);
            }
            //Display response result
            Console.WriteLine("Main Thread: Worker says: "+workerResponse);
            Console.WriteLine("Main Thread: Finished");

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }

        public void onCallBack(IAsyncResult result)
        {
            //recats result
            AsyncResult res = (AsyncResult)result;
            //retrieve delegate
            MyAsyncDelegate myDeleg = (MyAsyncDelegate)res.AsyncDelegate;
            //get response and set it to local variable
            workerResponse = myDeleg.EndInvoke(result);
            gotResponse = true;
        }
    }
}

Now lets talk about code:
1) Delegate – private delegate string MyAsyncDelegate(int dig1, int dig2);
the main thing to know about delegate is that delegate have to match to the method signature
in our case string is return type, dig1, dig2 – two integers as input params
2) Delegate Creation – MyAsyncDelegate myDelegate = new MyAsyncDelegate(new AsyncWorker().performLongAndHeavyCalculation);
if you will check “AsyncWorker” class, you would notice that string performLongAndHeavyCalculation(int, int) match to our delegate signature.
3) Executing Async with BeginInvoke – myDelegate.BeginInvoke(num1, num2, new AsyncCallback(onCallBack), null);
Async Execution consist of 3 params:

  • Method input – in our case num1 and num2 which are dig1 and dig2
  • Call back response – method which will be invoked when result is ready
  • object – in our case it is null

4) On Call back event we getting delegate reference back
5) and getting result value by calling myDeleg.EndInvoke(result);

as simple as that 🙂

here is console output:

Main Thread: Start
Main Thread: launching worker
Main Thread: worker executed
Wating for worker to complete his job....
Worker: Starting job
Wating for worker to complete his job....
Wating for worker to complete his job....
Wating for worker to complete his job....
Wating for worker to complete his job....
Wating for worker to complete his job....
Wating for worker to complete his job....
Worker: Job Complete
Main Thread: Worker says: Result of heavy calculation is: 40
Main Thread: Finished
Press any key to exit...

You can download Visual Studio Project from my:

Java Async Future

That is going to be my first post and today I will explain purpose of Java Future

The main purpose of Java Future is expecting returning value from paralel task in the future. For example if you execute new Thread you would be able to do some task in background however it is going to be difficult to return value from that thread once calculations were finished, we will have to use some kind of synchronized middle object as a storage.

Java Future is nearly the same Thread but with possibility to return value in the future. To demonstrate it we will implement simple task:

Task Description:

Download 4k (4096×2160 – 9.1Mb size) wallpaper image from URL (my DropBox) as parallel task, were executed worker would return String of the total KB were downloaded when task will be fully complete.

Implementation:

Lets start from the main class:

package implementation;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class AsyncMain {
	
	public static void main(String[] args)
	{
		new AsyncMain().startRoutine();
	}
	
	private void startRoutine()
	{
		//creating thread pool of single thread (but could be pool of many threads, I just don't need it for this demonstration)
		ExecutorService executor = Executors.newSingleThreadExecutor();
		//creating callable object which expected to return value of String type
		Callable<String> imageDownloader = new AsyncWorker();
		//Executing asynchronous thread which should return value in the future 
		Future<String> asyncThread = executor.submit(imageDownloader);
					
		//Waiting until async thread finish its job
		while (!asyncThread.isDone()) {
			
			try
			{
				//writing to the console once per sec
				System.out.println("Main: Worker still Downloading file...");
				Thread.sleep(1000);
				
			}
			catch(Exception e)
			{
				System.out.println("Main thread was interupted");
			}
		}
				

		String result = "";
		try {
			//getting return value from async thread
			result = asyncThread.get();
			//printing returned value from async thread to console
			System.out.println("Main: [Returned result from AsyncThread is: "+result+"]");
		} catch (Exception e) {
			e.printStackTrace();
		} 
			

		
		//Telling to pool executor to shutdown once it thread is finished
		executor.shutdown();
		
	}

	
}


As you can see, we create thread pool, define future callable and execute it.
Future has nice method isDone() which allow to check if parallel task was complete before trying to get value. However if you will try to get value without check isDone() it will blocked the thread until data will be available

Now lets look at the Worker or slave if you prefer:

package implementation;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;



public class AsyncWorker implements Callable<String>{

	@Override
	public String call() throws Exception {
		
		//variables used during the progress
        String result = null;
        int totalBytes = 0;
        int size;
        int sizeKb;
        float onePrcnt;
        byte data[] = new byte[1024];
        int count;
        float prevProcent = 0;
        
        //in / out streams
        BufferedInputStream in = null;
        FileOutputStream fout = null;
        
        //URLs to download: from / to
        String urlLink ="https://dl.dropboxusercontent.com/u/15715229/palousecanola.jpg";
        String outputPath = "C:/AsyncTest";
        String filename = "Palousecanola.jpg";

		try
        {
			//Create new url object
			URL url = new URL(urlLink);
			//opening connection
			URLConnection con = url.openConnection();
			//setting size of remote content
			size = con.getContentLength();
			sizeKb = size / 1024;
			onePrcnt = size / 100;
			//Closing connection ??? there should be more delicate way how to get size of downloadable content instead of opening and closing connection
			//but stream type of connection doesn't allow to get the size of entire stream, however download process is faster
			//Anyway we need size just to nicely represent amount of downloaded in percentage 
			con = null;
			
			//Preparing input stream
            in = new BufferedInputStream(url.openStream());
            
            //prepare output file location;
            new File(outputPath).mkdirs();
            //Preparing output file stream
            fout = new FileOutputStream(outputPath+"/"+filename);
            //downloading file
            while ((count = in.read(data, 0, 1024)) != -1)
            {
            	//Calculating total of bytes downloaded
            	totalBytes += count;
            	//writing to the file new bytes
                fout.write(data, 0, count);
                //display console message once per one full percent or more then one
                if(totalBytes >= onePrcnt)
                {
                	//calculation in percentage how much in total was downloaded
                	float totalPrcnt = totalBytes / onePrcnt;
                	//checking if total minus previous total would be more then 1%
                	if(totalPrcnt - prevProcent > 1)
                	{
                		prevProcent = totalPrcnt;
                		//Then display message
                		System.out.println("AsyncWorker: [Downloaded: "+(int)totalPrcnt+"% or "+totalBytes / 1024+"Kb from: "+sizeKb+"]");
                	}
                }
                	
            }
            
            //Setting return statement
            result = "Download of total "+totalBytes / 1024+"KB was complete";
        }
		catch(Exception e)
		{
			//setting return statement to contain exception message 
			result = "Application was Scrashed because of: "+e;
		}
        finally
        {
        	//closing [in] and [out] streams regardless was there exception or not
            if (in != null)
                in.close();
            if (fout != null)
                fout.close();
        }
		//internal message of complete state
		System.out.println("AsyncWorker: [Download Complete!]");
		//returning value
		return result;
	}

}

Our worker just connects to web (my drop box file) and try to download it.
I had to make connection to the web twice just to get file size for nice representation of download progress in percentage, however downloading file through the input stream does not allow you to query content weight but is much faster (you can test it your self), so I had to open connection get file size, close connection and open stream connection again.

Returned String is a result of downloaded file size or crash report, in both ways async task return value of String type to main thread.

This project source can be downloaded from my: