Вызов Coroutine API завершается только после сна нить - PullRequest
0 голосов
/ 15 мая 2019

Я довольно новичок в концепции сопрограмм.Теперь у меня возникла эта проблема, когда я вызываю свою функцию Coroutine, она возвращает пустой объект, когда я не использую System.Threading.Thread.Sleep () ;.Но когда я использую System.Threading.Thread.Sleep (int);Он ожидает завершения метода сна, прежде чем продолжить код.Я понимаю, что это, вероятно, связано с тем, что они работают в одном потоке, но даже мои функции отладки до того, как метод sleep не будет печатать, пока не будет выполнена функция sleep.здесь действительно может быть какая-то помощь!

Я попробовал это сделать с синхронными вызовами, но это просто останавливает мой макет.

IEnumerator PostRequestBearerToken(string uri)
    {
        string authorization = APIHelpers.authenticate("user", "pass");
        WWWForm form = new WWWForm();
        form.AddField("grant_type", "client_credentials");

        using (UnityWebRequest www = UnityWebRequest.Post(uri, form))
        {
            www.SetRequestHeader("AUTHORIZATION", authorization);
            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log(www.error);
            }
            else
            {
                Debug.Log("Post request complete!" + " Response Code: " + www.responseCode);
                string responseText = www.downloadHandler.text;
                Debug.Log("Response Text:" + responseText);
                Debug.Log("Form upload complete!");

                //deserialize bearertoken
                BearerObject myObject = JsonUtility.FromJson<BearerObject>(www.downloadHandler.text);
                Debug.Log("json : " + myObject.ToString());
                //BearerTokenSingleton.getInstance();
                BearerTokenSingleton.getInstance().SetBearerToken(myObject);
                Debug.Log(BearerTokenSingleton.getInstance().GetBearerToken().ToString());
            }
        }
    }
void Update()
   {
       if (!loadFirstFrame)
       {
           loadFirstFrame = true;
       }
       else if (loadFirstFrame)
       {
           StartCoroutine(PostRequestBearerToken(APIHelpers.bearerString));

           //go to next scene            
           System.Threading.Thread.Sleep(5000);
           SceneManager.LoadScene(2);
       }

   }

1 Ответ

3 голосов
/ 15 мая 2019

Это из-за метода SceneManager.LoadScene.Сопрограммы запускаются в отдельных потоках.Поскольку вы запускаете сопрограмму и сразу же загружаете новую сцену, у вас нет времени, чтобы запустить сопрограмму до того, как выгрузится текущая сцена (и объект сценария).Вызов Thread.Sleep вводит задержку, которая дает достаточно времени для завершения сопрограммы до загрузки сцены.

Чтобы обойти это, вы можете использовать флаг (на самом деле я использую два, так что вы не пинаетевыключить сопрограмму несколько раз):

private bool _postComplete = false;
private bool _startedPost = false;

IEnumerator PostRequestBearerToken(string uri)
{
    string authorization = APIHelpers.authenticate("user", "pass");
    WWWForm form = new WWWForm();
    form.AddField("grant_type", "client_credentials");

    using (UnityWebRequest www = UnityWebRequest.Post(uri, form))
    {
        www.SetRequestHeader("AUTHORIZATION", authorization);
        yield return www.SendWebRequest();

        if (www.isNetworkError || www.isHttpError)
        {
            Debug.Log(www.error);
        }
        else
        {
            Debug.Log("Post request complete!" + " Response Code: " + www.responseCode);
            string responseText = www.downloadHandler.text;
            Debug.Log("Response Text:" + responseText);
            Debug.Log("Form upload complete!");

            //deserialize bearertoken
            BearerObject myObject = JsonUtility.FromJson<BearerObject>(www.downloadHandler.text);
            Debug.Log("json : " + myObject.ToString());
            //BearerTokenSingleton.getInstance();
            BearerTokenSingleton.getInstance().SetBearerToken(myObject);
            Debug.Log(BearerTokenSingleton.getInstance().GetBearerToken().ToString());
        }
        _postComplete = true;
    }
}

И затем использовать это в методе Update:

   void Update()
   {
       if (!loadFirstFrame)
       {
           loadFirstFrame = true;
       }
       else if (loadFirstFrame)
       {
           if (!_startedPost)
           {
               StartCoroutine(PostRequestBearerToken(APIHelpers.bearerString));
               _startedPost = true;
           }         

           if (_postComplete)
               SceneManager.LoadScene(2);
       }
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...