- Home /
StartCoroutine_Auto can only be called from the main thread.
Hi I'm having some problems with my code, I can assure that worked well, but now I jump with coroutines error ... Here is the code to see if anyone can help me ... I am using Ngui, then when you press a button called one of the coroutines, but now I get the error.
 public IEnumerator WaitAlertView()
     {
         yield return new WaitForSeconds (0.2f);
         EtceteraBinding.hideActivityView();
         yield return new WaitForSeconds (0.6f);
         EtceteraBinding.showAlertWithTitleMessageAndButton("Error","Es posible que el nombre de usuario ya exista, por favor escoge otro nombre","Vale");
         
     }
     
     
     public IEnumerator WaitAlertView2()
     {
         
         yield return new WaitForSeconds (0.2f);
         EtceteraBinding.hideActivityView();
         yield return new WaitForSeconds (0.6f);
         EtceteraBinding.showAlertWithTitleMessageAndButton("Error","Se ha cancelado el registro","Vale");
     }
     
     public IEnumerator WaitAlertView3()
     {
         
         yield return new WaitForSeconds (0.2f);
         EtceteraBinding.hideActivityView();
         yield return new WaitForSeconds (0.6f);
         EtceteraBinding.showAlertWithTitleMessageAndButton("Error","El Login ha fallado, comprueba que su usuario y password son correctos","Vale");
     }
     
     public IEnumerator WaitAlertView4()
     {
         
         yield return new WaitForSeconds (0.2f);
         EtceteraBinding.hideActivityView();
         yield return new WaitForSeconds (0.6f);
         cargado = true;
     }
     
     
     
     // Update is called once per frame
     public void Update () 
     {
         
         
         myName = nameuser.text;
         myPassword = password.text;
         myEmail = email.text;
         loginUser2 = loginName.text;
         loginPass2 = loginPass.text;
         NivelCargado();
     
     
     
     }
     
     // Accion que se dispara cuando se pulsa el boton unirse a PLM
     public void SendUserToParse()
     {
         EtceteraBinding.showBezelActivityViewWithLabel("Creando usuario, un momento por favor");
         // Crear nuevo usuario en Base de datos
         
         var user = new ParseUser()
         {
             
         Username = myName,
         Password = myPassword,
         Email= myEmail
             
             
         };
         
         Task signUpTask = user.SignUpAsync().ContinueWith(t =>
         {
             if (t.IsCanceled)
             {
                 
                 StartCoroutine(WaitAlertView2());
             
                 
                 
             }
             else if ( t.IsFaulted)
             {
                 
                 
                 StartCoroutine(WaitAlertView());
                 
                 
             }
             else
             {
                 
                     StartCoroutine(WaitAlertView4());
             }
             
         });
         
         
     }
     
     // Accion que se dispara cuando se pulsa el boton Login
     public    void Login()
     {
         EtceteraBinding.showBezelActivityViewWithLabel("Conectando, un momento por favor");
         
         
         ParseUser.LogInAsync(loginUser2,loginPass2).ContinueWith(t=>
         {
             
             if (t.IsFaulted || t.IsCanceled)
             {
                 
                 StartCoroutine(WaitAlertView3());
                 
             }
             
             
             else 
             {
                 StartCoroutine(WaitAlertView4());
                 
             }
             
         
         
         });
         
         
     }
     
     
     // Cuando el login se ha creado con exito cambiamos de escena
     public void NivelCargado ()
     {
         
         if (cargado)
         {
             
             
             Application.LoadLevel ("EscenadeJuego");
         }
         
     }
 
Answer by Wolkenschauer · Feb 15, 2014 at 12:06 AM
well it sounds more like you're looking for a Invoke method with all the waiting to me, however if you want to start a coroutine from a different thread than the unity main thread, therefore you could create a list and add whatever the coroutine is supposed to do to it as for instance an action and invoke the action on a gameobject within the game loop (i use this kind of approach whenever i have network calls which are by nature asnchronious ...
1) create a gameobject in your scene and add a this script:
 public class DoOnMainThread : MonoBehaviour {
     
     public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action>();
     
     public virtual void Update()
     {
         // dispatch stuff on main thread
         while (ExecuteOnMainThread.Count > 0)
         {
             ExecuteOnMainThread.Dequeue().Invoke();
         }
     }
 }
2) Add your coroutine action into the queue whenever you want to call it like this:
 DoOnMainThread.ExecuteOnMainThread.Enqueue(() => {  StartCoroutine(WaitAlertView4()); } );
it will be executed next opportunity the main thread can, or rather when the game object will call it's update method
After days of search this works perfectly for me. $$anonymous$$any thanks!
This needs to be the accepted answer. Very nice - especially for asynchronious execution such as networking as you mention!
Very good answer ! $$anonymous$$aybe it's obvious but in order to use Queue class you have to include:
 using System.Collections.Generic;
Thank you very much, so helpful! But maybe there need queue data lock before ExecuteOn$$anonymous$$ainThread.Dequeue().Invoke();? 
Your answer
 
 
              koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                