Error retrieving large data from server and parse it using a Thread

Hi,

I’m implementing an Android application using Unity that will retrieve some data from myserver the first time it’s started. This data has text and images.

In my server I’m using Base64 to code the images and return them in a JSON string. This way I only need a single request to get all the data, but its result is really large. If I try to access WWW.text it takes some seconds to process it.

To parse the JSON I’m using SimpleJSON.JSON.Parse. Since this takes some time to finish I decided to use it in a different Thread.

My problem is accessing WWW.text. If I do it inside the Thread I get this error:

get_isDone  can only be called from the main thread

And if I use it outside the Thread my application stops for several seconds.

This is my code:

void OnGUI(){ 
        if(catalogWWW == null){
			catalogWWW = new WWW(myURL);
		}
		
		if(!catalogWWW.isDone || parseJSONStatus <2)
			updateProgressBar();
		
		if(catalogWWW.isDone){
			if(parseJSONStatus == 0){
				parseJSONStatus = 1;
				
				Thread t = new Thread(parseWWWJSON);
				t.Start(catalogWWW);
			}
			
			if(parseJSONStatus == 2){
				Debug.Log("FINISHED!");
			}
		}
}

public void parseWWWJSON(object data) {
	catalogData = SimpleJSON.JSON.Parse(((WWW)data).text);
	parseJSONStatus = 2;
}

With this code I get the error: get_isDone can only be called from the main thread.

If I use t.Start(catalogWWW.text) instead, my progress bar is updated while downloading, then it stops like 5 seconds (catalogWWW.text is being executed) and then it continues to be updated.

How can I fix it?

Thanks!

I don’t really get why you use this strange statemachine pattern and why it is implemented in OnGUI? That’s really strange since OnGUI is ment for GUI and rendering only. Also since you use a Thread you have to take care of synchronising the threads.

To fix the error you get you should read the string into a temp-variable and pass this to the thread instead of the WWW object. If that takes too long you might have to use System.Net classes to do your server request and do everything in your background thread.

I would do something like this (quick and dirty :D):

IEnumerator LoadData()
{
	WWW www = new WWW("URL");
	yield return www;
	
	string data = www.text;
	object lockHandle = new System.Object();
	bool done = false;
	JSONNode result = null;
	
	var myThread = new System.Threading.Thread(()=>
	{
		result = JSON.Parse(data);
		lock(lockHandle)
		{
			done = true;
		}
	});
	myThread.Start();
	
	while(true)
	{
		yield return null;
		lock(lockHandle)
		{
			if (done)
			{
				break;
			}
		}
	}
	
	var DDD = result["somedata"];
}

void Start()
{
	StartCoroutine(LoadData());
}