Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Palouxic · Jun 28, 2013 at 12:04 PM · wwwjsonthreads

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!

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Benproductions1 · Jun 28, 2013 at 12:05 PM 1
Share

Generally, the Unity API is not thread safe

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Jun 28, 2013 at 12:56 PM

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());
 }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Palouxic · Jun 28, 2013 at 04:20 PM 0
Share

Sorry if the code is weird, I'm new with Unity ^^

$$anonymous$$y application will have some 2D menus and some 3D scenes. In this one I wanted to create something similar to an Android's ListView (2D list). I'm going to build this List with the data retrieved, and since I saw that Buttons and stuff like this are usually placed in onGUI I implemented it in there.

I don't have the code here right now, so I won't be able to prove your answer until monday. I'll let you know if it worked :)

Thank you!

avatar image Palouxic · Jul 01, 2013 at 11:18 AM 0
Share

I tried your code and it worked, although I finally decided to do several requests to the server to get the images since SimpleJSON was really slow parsing long data. I used your structure in my code and now it's way more clear. Thank you!

avatar image Bunny83 · Jul 01, 2013 at 01:00 PM 0
Share

Hmm, i know that doing string + char for each char is quite inefficient because the whole temp-string needs to be copied each time. For most JSON stuff that's not really a problem, but if a single field / Token is quite large it will of course be quite slow.

It might help to replace the Token string with a StringBuilder, but i would have to do some performance tests myself. For small strings a StringBuilder usually yields even worse performance than normal string concat. $$anonymous$$aybe i implement a switch in the future so the user can select which mode it should use.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

18 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Parse json/application with unity. 1 Answer

place data locally from install 0 Answers

IOS memory leak because of WWW object 1 Answer

how to find if WWW Post Request is succesful? 2 Answers

Load image from document directory for iphone 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges