在Unity中,异步函数不等待结果。

问题描述 投票:0回答:1

我想用下一个函数等待,先完成上一个函数。但在完成之前我有返回。下面是代码。

private async Task SetupPlayerDatabase()
{
    Task<string> signInWithPlayGames = SignIn.SignInWithPlayGames();
    userId = await signInWithPlayGames;
    Debug.Log("USER ID: " + userId);
}

和sceound类。

and SignInWithPlayGames:
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using Firebase.Auth;

public class SignIn : MonoBehaviour
{
    private static string userId;

    void Awake () {
        // Initialize Play Games Configuration and Activate it.
        PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().RequestServerAuthCode(false /*forceRefresh*/).Build();
        PlayGamesPlatform.InitializeInstance(config);
        PlayGamesPlatform.Activate();
        //Debug.LogFormat("SignInOnClick: Play Games Configuration initialized");
    }

                // HERE IS THIS FUNCTION ↓ ↓ ↓ ↓ ↓ ↓ 

    public static async Task<string> SignInWithPlayGames () {
        await Task.Run(() => {
        Debug.LogError("SignIn.SignInWithGooglePlay Task is running");
        // Initialize Firebase Auth
        Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance; // Sign In and Get a server auth code.
        UnityEngine.Social.localUser.Authenticate((bool success) =>
        {
            if (!success) {
                Debug.LogError ("SignInOnClick: Failed to Sign into Play Games Services.");
                return;
            }
            string authCode = PlayGamesPlatform.Instance.GetServerAuthCode();
            if (string.IsNullOrEmpty(authCode))
            {
                Debug.LogError("SignInOnClick: Signed into Play Games Services but failed to get the server auth code.");
                return;
            }
            //Debug.LogFormat("SignInOnClick: Auth code is: {0}", authCode); // Use Server Auth Code to make a credential
            Firebase.Auth.Credential credential = Firebase.Auth.PlayGamesAuthProvider.GetCredential(authCode); // Sign In to Firebase with the credential
            auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
            if (task.IsCanceled) {
                Debug.LogError ("SignInOnClick was canceled.");
                return;
            }
            if (task.IsFaulted) {
                Debug.LogError("SignInOnClick encountered an error: " + task.Exception);
                return;
            }
            Firebase.Auth.FirebaseUser newUser = task.Result;
            Debug.LogFormat("SignInOnClick: User signed in successfully: {0} ({1})", newUser.DisplayName, newUser.UserId);
            userId = newUser.UserId;
            // i would like to return userId here, but i cannot
            });
        });
        });
        Debug.LogError("SignIn.SignInWithGooglePlay return: " + userId);
        return userId; // here i return before it have value
    }
}

Debugg显示我首先有 return userId; 在这之后,我有 userId = newUser.UserId;. 所以我首先要返回空字符串,然后再得到userId的值。

我不能写 return userId; 一行 userId = newUser.UserId; 因为它是lambda和返回void。

我怎样才能修正它,使这个函数在正确的地方和时刻完成?要返回 userId 在这个字符串中取值后,如何处理?

c# database firebase unity3d lambda
1个回答
1
投票

代码中的return语句将在任务结束前执行,因为你正在使用 Task.Run 没有结果。通过改变任务来返回一个字符串,即创建一个 Task<string> 如图所示,它将等待一个结果,然后继续下一行。

public static async Task<string> SignInWithPlayGames () {
    TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
    Task.Run(() => {
        Debug.LogError("SignIn.SignInWithGooglePlay Task is running");
        // Initialize Firebase Auth
        Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance; // Sign In and Get a server auth code.
        UnityEngine.Social.localUser.Authenticate((bool success) =>
        {
            if (!success) {
                Debug.LogError ("SignInOnClick: Failed to Sign into Play Games Services.");
                tcs.SetResult(null);
            }
            string authCode = PlayGamesPlatform.Instance.GetServerAuthCode();
            if (string.IsNullOrEmpty(authCode))
            {
                Debug.LogError("SignInOnClick: Signed into Play Games Services but failed to get the server auth code.");
                tcs.SetResult(null);
            }
            //Debug.LogFormat("SignInOnClick: Auth code is: {0}", authCode); // Use Server Auth Code to make a credential
            Firebase.Auth.Credential credential = Firebase.Auth.PlayGamesAuthProvider.GetCredential(authCode); // Sign In to Firebase with the credential
            auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
            if (task.IsCanceled) {
                Debug.LogError ("SignInOnClick was canceled.");
                tcs.SetResult(null);
            }
            if (task.IsFaulted) {
                Debug.LogError("SignInOnClick encountered an error: " + task.Exception);
                tcs.SetResult(null);
            }
            Firebase.Auth.FirebaseUser newUser = task.Result;
            Debug.LogFormat("SignInOnClick: User signed in successfully: {0} ({1})", newUser.DisplayName, newUser.UserId);
            tcs.SetResult(newUser.UserId);
            });
        });
    });
    return await tcs.Task;
}

0
投票

我有解决办法。我必须把授权和方法分开来等待,因为授权不能从非主线程调用(在Unity中)。现在它的工作原理是这样的。

private async Task SetupPlayerDatabase()
{
    SignIn signIn = new SignIn();
    Task<string> checkAuthorizedCorrect = signIn.CheckAuthorizedCorrect();
    userId = await checkAuthorizedCorrect;
    Debug.Log("USER ID: " + userId);
}

and:

using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using Firebase.Auth;


public class SignIn : MonoBehaviour
{
    private static bool playerIsAuthorized;
    private static string userId;

    // Use this for initialization
    void Awake () {
        // Initialize Play Games Configuration and Activate it.
        PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().RequestServerAuthCode(false /*forceRefresh*/).Build();
        PlayGamesPlatform.InitializeInstance(config);
        PlayGamesPlatform.Activate();
        Debug.LogFormat("SignInOnClick: Play Games Configuration initialized");
        SignInWithPlayGames();
    }

public async Task<string> CheckAuthorizedCorrect () {
    await Task.Run(() => {
        while (playerIsAuthorized == false)
        {
            Debug.Log("Waiting for userId");
        }
    });
    return userId;
}

public static void SignInWithPlayGames () {
        // Initialize Firebase Auth
        Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
        Debug.Log("Sign In and Get a server auth code.");
        UnityEngine.Social.localUser.Authenticate((bool success) =>
        {
            if (!success) {
                Debug.LogError ("SignInOnClick: Failed to Sign into Play Games Services.");
                return;
            }
            string authCode = PlayGamesPlatform.Instance.GetServerAuthCode();
            if (string.IsNullOrEmpty(authCode))
            {
                Debug.LogError("SignInOnClick: Signed into Play Games Services but failed to get the server auth code.");
                return;
            }
            Debug.LogFormat("SignInOnClick: Auth code is: {0}", authCode); // Use Server Auth Code to make a credential
            Firebase.Auth.Credential credential = Firebase.Auth.PlayGamesAuthProvider.GetCredential(authCode); // Sign In to Firebase with the credential
            auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
            if (task.IsCanceled) {
                Debug.LogError ("SignInOnClick was canceled.");
                return;
            }
            if (task.IsFaulted) {
                Debug.LogError("SignInOnClick encountered an error: " + task.Exception);
                return;
            }
            Firebase.Auth.FirebaseUser newUser = task.Result;
            Debug.LogFormat("SignInOnClick: User signed in successfully: {0} ({1})", newUser.DisplayName, newUser.UserId);
            userId = newUser.UserId;
            playerIsAuthorized = true;
            });
        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.