我想用下一个函数等待,先完成上一个函数。但在完成之前我有返回。下面是代码。
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
在这个字符串中取值后,如何处理?
代码中的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;
}
我有解决办法。我必须把授权和方法分开来等待,因为授权不能从非主线程调用(在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;
});
});
}
}