首页 > 解决方案 > 协程中的异步函数在 Android 上不起作用

问题描述

我正在尝试在我的 Unity 项目中创建使用 Facebook 登录流程。我正在使用 Facebook SDK 和 Firebase 对用户数据进行身份验证并将其存储在在线数据库中。

只有当用户不存在时,我才需要更新数据库。所以我正在使用协程

    public void someCodeHere(params){
        StartCoroutine(waitForTask(task, uid, name, email));
}

    IEnumerator waitForTask(Task<DataSnapshot> task, string uid, string name, string email)
    {
        while(!task.IsCompleted)
        {
            Debug.Log("Wait task to coplete");
            yield return new WaitForSeconds(1);
        }
        Debug.Log(task.Result.GetRawJsonValue());
        if(task.Result.GetRawJsonValue() == null || task.Result.GetRawJsonValue() == "")
        {
            HardUpdateUser(uid, name, email);
        }
        else
        {
            SetExistingUser(task);
        }
    }

SetExistingUser 在编辑器和设备上完美运行,但是 HardUpdateUser(uid, name, email); 不能在设备上工作,但在统一编辑器中工作得很好。

这是函数内部的代码:

        var status = reference.Child("users").Child(userId).SetRawJsonValueAsync(json).ContinueWith(task =>
        {

            if (task.IsCanceled)
            {
                Debug.LogError("CreateUpdateUserInDB was canceled.");
                return;
            }
            if (task.IsFaulted)
            {
                Debug.LogError("CreateUpdateUserInDB encountered an error: " + task.Exception);
                return;
            }
            Debug.LogFormat("User CreateUpdateUserInDB successfully: {0} ({1})",
                user.userName, userId);

        });

标签: androidfirebaseunity3dfirebase-realtime-databasec#-4.0

解决方案


所以。我没有得到日志,因为我没有足够的时间,而且我想我太懒了。无论如何,我为我的问题找到了一些解决方法。

我没有提到的事情是我StartCoroutine(waitForTask(task, uid, name, email));在另一个协程中启动协程(当然是在另一个协程中)。所以我有很多courtines。他们中的大多数人都在等待来自前一个函数等的一些对象。我在 while 循环中使用了一些计数器。例如

while(obj == null && wait > 0) {
    wait--; 
    yield return new WaitForSceonds(1);
}
wait = 15;
//run next coroutine 

并且等待变量通常是少数协程之一。所以我改变了什么:

  1. 我不再等待对象,而是等待完成特殊任务(例如task.IsCompleted
  2. 我已将等待变量更改为时间戳。(例如,我不想等待用户登录超过 15 秒)

所以我的根本问题不在我在问题中提到的代码中。

当我有时间调查 Android 日志并找出协程堆积的原因时,我会更新我的答案。

这是一个带有时间戳的示例:

    private IEnumerator SetUserNameToTheTop()
    {
        while (ux.GetCurrentUser() == null && (DateTime.Now - dataTime).TotalSeconds < 15)
        {
            pendingTxt.text = (DateTime.Now - dataTime).TotalSeconds.ToString();
            Debug.Log("WAIT FOR ERROR");
            yield return new WaitForSeconds(1);
        }
        if (ux.GetCurrentUser() != null && ux.GetCurrentUser().userName != "")
        {
            ActivateMenu();
        }
        else
        {
            PENDING_MSG = "USER WASN'T FOUND, TRY TO SIGN UP FIRST";
            pendingTxt.text = PENDING_MSG;
            isFailed = true;
            FBButtons.SetActive(true);
        }
    }

推荐阅读