question

nannie avatar image
nannie asked

async method to get callback data

I was trying to check whether the player has any contact email set up. But after testing I realized that the "GetPlayerProfile" will require some time to get the info from (possibly) the server-side and process the data in the callback. So I google for a bit, and people suggesting using async method to wait for the result. So I came up with the following piece of code, but when Unity runs the following code, it seems to freeze (possibly dead loop). Any suggestions would be really appreciated!

public static bool PlayerHasContactEmail()
	{
		Func<Task<bool>> PlayerHasContactEmailDelegate = async () =>
		{
			TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
			var request = new GetPlayerProfileRequest()
			{
				PlayFabId = PlayFabSettings.staticPlayer.PlayFabId,
				ProfileConstraints = new PlayerProfileViewConstraints() { ShowContactEmailAddresses = true },
			};


			var callBackResult = false;


			PlayFabClientAPI.GetPlayerProfile(
				request,
				success =>
				{
					tcs.SetResult(true);
					callBackResult = !success.PlayerProfile.ContactEmailAddresses.IsNullOrEmpty();
				},
				fail =>
				{
					tcs.SetResult(true);
					callBackResult = false;
					Debug.LogError(fail.Error.ParseReadableString());


				});


			Debug.Log("Waiting for call back result");
			await tcs.Task;
			Debug.Log($"Result Returned, player has ContactEmail: {callBackResult}");


			return callBackResult;
		};


		var result = PlayerHasContactEmailDelegate.Invoke();
		return result.Result;
	}
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Seth Du avatar image
Seth Du answered

You may note that the reason why the variable always null can be caused by your code out of callback result. Because the API is async, which means it doesn't have time to send back the result to the check condition. I have slightly changed your code to implement the email checking function. Please note the result returned from different places.

    void Start()
    {
        PlayFabClientAPI.LoginWithCustomID(
            new LoginWithCustomIDRequest
            {
               CustomId = "xxxxxxxx",
               TitleId = "xxxx"
            },
            succ => {
                print("login Successful");
                if (PlayerHasContactEmail())
                // the condition is always false here because there is no enough time to recevie the callback
                {
                    print("Check Email out of callback: Have Email");
                }
                else
                {
                    print("Check Email out of callback: No Email");
                }
            },
            fail => {
                print(fail.GenerateErrorReport());
            });
    }

    public static bool PlayerHasContactEmail()
    {
        bool result = false;
        var request = new GetPlayerProfileRequest()
        {
            PlayFabId = PlayFabSettings.staticPlayer.PlayFabId,
            ProfileConstraints = new PlayerProfileViewConstraints() { ShowContactEmailAddresses = true },
        };
        PlayFabClientAPI.GetPlayerProfile(
            request,
            success =>
            {
                bool isEmpty =  !Convert.ToBoolean( success.PlayerProfile.ContactEmailAddresses.Count());
                // Check if the address is empty inside the callback. 
                if (isEmpty)
                {
                    result = false;
                    print("Check Email inside the callback: No Email");
                }
                else
                {
                    result = true;
                    print("Check Email inside the callback: " + success.PlayerProfile.ContactEmailAddresses[0].EmailAddress);
                }
            },
            fail =>
            {
                result = false;
                print(fail.GenerateErrorReport());
            });
        return result;
    }
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Seth Du avatar image
Seth Du answered

According to your code, I assume you are using Unity SDK, you don’t need to define additional task for executing APIs because they are already async. For example, in PlayFabClientAPI.GetPlayerProfile(request, success, fail), anything you have defined in “success” function will be executed only when the client receives callback result, and so as “fail” function.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

nannie avatar image nannie commented ·

Thank you, but I want to write my own function to return a bool to check whether a user has set up a contact email or not. I am not sure if I can do that, in this case, using the success and fail actions to return a bool. But the following code wouldn't work, it will always return false at the time when I call the function "PlayerHasContactEmail()"(the default value of result as false before callback), and it will also return another bool after the callback.

public static bool PlayerHasContactEmail()
{
	var result = false;
	var request = new GetPlayerProfileRequest()
			{
				PlayFabId = PlayFabSettings.staticPlayer.PlayFabId,
				ProfileConstraints = new PlayerProfileViewConstraints() { ShowContactEmailAddresses = true },
			};


	PlayFabClientAPI.GetPlayerProfile(
				request,
				success =>
				{
					result = !success.PlayerProfile.ContactEmailAddresses.IsNullOrEmpty();
				},
				fail =>
				{
					result = false;
					Debug.LogError(fail.Error.ParseReadableString());
 
 
				});
	return result;
}

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.