1

I'm launching a WWW get request and upon receiving the response, I want to parse the received string into a JSON. The problem is that due to the very large size of the response, getting the response string using www.text blocks the UI.

I've tried putting the www.text method on another thread, however Unity isn't thread-safe and I get an exception when I tried to access www.text.

Are there any alternatives to getting the string from a www request?

EDIT: It's not the speed of the request that's bothering me (e.g. how long it takes to download the file) but the time it takes to get the string from the completed WWW object. I've tried doing this inside a coroutine, however I believe WWW.text is an atomic operation aka you can't do it over a number of frames.

EDIT2: Code: coroutine to start the request

sender.StartCoroutine(GetSessionWithPositions(sender, URL));

static IEnumerator GetSessionWithPositions(UI.HistoryTableViewController sender, string URL) {
        WWW request = new WWW(URL);
        yield return request;
        isMakingARequest = false;
        if (string.IsNullOrEmpty(request.error)) {
            Debug.Log(Time.time.ToString());
            sender.ReceivedShotsPosition(request);
        } else {
            Debug.Log("GetSessionWithPositionsRequest failed with error: " + request.error);
        }
    }

Code that launches the deserialize Thread

public void ReceivedShotsPosition(WWW request) {
            Thread deserializeThread = new Thread(new ParameterizedThreadStart(Deserialize));
            deserializeThread.Start((request as object));
            StartCoroutine(CheckIfDone());
        }

The code that handles the request

private void Deserialize(object request) {
            WWW wwwObject = request as WWW;
            JSONObjects.Session session = Utility.JsonHelper.DeserializeJSON<JSONObjects.Session>(wwwObject.text);
            int index = 0;
            dataSource = new Models.ShotDataObject[session.Shots.Length];
            foreach (JSONObjects.Shot JSONShot in session.Shots) {
                dataSource[index++] = new Models.ShotDataObject(JSONShot);
            }
            finishedSerializing = true;
        }

The CheckIsDone coroutine simply checks that bool and updates the UI if it's set to true.

EDIT3: The response is a JSON string.

EDIT4: UnityThread variant

private void Deserialize(object json) {
            WWW request = json as WWW;
            string jsonString;
            UnityThread.executeInUpdate(() => {
                jsonString = request.text;
                JSONObjects.Session session = Utility.JsonHelper.DeserializeJSON<JSONObjects.Session>(jsonString);
                int index = 0;
                dataSource = new Models.ShotDataObject[session.Shots.Length];
                foreach (JSONObjects.Shot JSONShot in session.Shots) {
                    dataSource[index++] = new Models.ShotDataObject(JSONShot);
                }
                finishedSerializing = true;
            }
            );

        }

Doesn't work as intended, same issue as before.

Mihai Stan
  • 143
  • 1
  • 13
  • *"Unity isn't thread-safe"* - do you mean when accessing Unity API? It's better if you post exception you are getting, that should be pretty common mistake and there should be an answer somewhere. Maybe unity has alternative to thread, but in simplest approach you can use `Update()` and signaling to pass result from another thread. Look e.g. [here](http://answers.unity3d.com/questions/1079013/c-sockets-multi-threading.html). – Sinatr May 10 '17 at 12:14
  • have you tried `async`, `await`? I don't know much about unity but if this is in c# code I would think you could use that to keep the UI going. – interesting-name-here May 10 '17 at 12:15
  • 1
    You can use `WebRequest` with `ThreadPool`. Check the duplicated question about slow `WWW`. for how to do that. – Programmer May 10 '17 at 12:17
  • @Programmer Looking at the possibly duplicated question, it doesn't solve my problem as it's not the actual request taking a long time to complete, but getting the text as a string from the WWW object that's taking a long time. – Mihai Stan May 10 '17 at 12:29
  • @Sinatr "get_isDone can only be called from the main thread." – Mihai Stan May 10 '17 at 12:29
  • `WWW` is slow while processing the data. Try that solution. Just try it. You should also post your original code since no one knows what it looks like. Also, you haven't mentioned what type of data is that. A file? A text data? video? – Programmer May 10 '17 at 12:33
  • @Programmer The reason i'm not that fond of trying the UnityThread solution is because it uses coroutines, which I have already tried and had no success in solving my issue. I've added the code. – Mihai Stan May 10 '17 at 13:01
  • No. `UnityThread` uses C# Thread... I am %100 sure because I wrote it. If you are %100 sure that freezing happens with `WWW.text` or the `WWW` API but not the Json API then use that answer. Remember, there are two options in that answer. The solution answer that requires `UnityThread` is what you should use. I even linked the file there. Finally, make sure to uncomment `UnityThread.initUnityThread();` in the `Awake` function. You need that. – Programmer May 10 '17 at 13:08
  • Any update? Did it work? – Programmer May 10 '17 at 18:43
  • I haven't got around to doing it yet. I'll do it later today and get back to you. – Mihai Stan May 11 '17 at 05:16
  • @Programmer gave it a go, doesn't seem to work. Have a look if you want. – Mihai Stan May 11 '17 at 11:19
  • Why are you doing this? Why don't you just read the answer from the duplicated question. `WWW` is **not** used anywhere. The first answer uses `UnityWebRequest` and the second answer uses C# `WebRequest` with `UnityThread` and `Thread` pool. The `WWW` class is **not** used anywhere there. If you read that properly and copy and paste the code from the second answer, you would have solved your problem long time ago. Just stop that and read that answer. It applies to your problem. – Programmer May 11 '17 at 11:24
  • I stand corrected. It works now. Thank you! – Mihai Stan May 11 '17 at 11:44

0 Answers0