协程api调用仅在线程睡眠后完成

时间:2019-05-15 12:07:48

标签: c# unity3d

我对协程的概念很陌生。现在我遇到了这个问题,当我调用Coroutine函数时,当我不使用它时,它会返回一个空对象 System.Threading.Thread.Sleep();。但是当我使用System.Threading.Thread.Sleep(int);在继续执行代码之前,它将等待直到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 个答案:

答案 0 :(得分:3)

这是因为有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);
       }
   }