Reauth on List Friends Async fails on current sync thread

Hi, I’m using Nakama with Unity SDK

After we call some API to nakama, we usually checks whether the token if expired or not, if it is we re-auth and then recalls that API, generally it looks like this

ListGuild-> result -> check error if session expires -> reauth -> ListGuild again

The problem is, some API success while other fails.

Why do auth in this succeeds


public void GuildList(string nameFilter)
{
    Task<IApiGroupList> listTask = client.ListGroupsAsync(session, nameFilter, 30);
    listTask.ContinueWith((task) =>
    {
        bool success = !(task.IsCanceled || task.IsFaulted);
        if(success)
        {
            // Do something if success
        }
        else
        {
            Exception exception = task.Exception.InnerException; 
            if(exception is ApiResponseException)
            {
                var e = exception as ApiResponseException;
                if(e.StatusCode == 401)
                {
                    Auth(()=>
                    { 
                        GuildList(nameFilter); 
                    });
                }
            }
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

void Auth(Action onFinish)
{
    Task<ISession> sessionTask = client.AuthenticateDeviceAsync(deviceId);
    sessionTask.ContinueWith((task) =>
    {
        bool success = !(task.IsCanceled || task.IsFaulted);
        if(success)
        {
            onFinish();
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

while auth in this fails?

public void FriendsList(int state)
{
    Task<IApiFriendList> listTask = client.ListFriendsAsync(session, state, listFriendLimit, null);
    listTask.ContinueWith((task)=>
    {
        bool success = !(task.IsCanceled || task.IsFaulted);
        if(success)
        {
            // Do something if success
        }
        else
        {
            Exception exception = task.Exception.InnerException; 
            if(exception is ApiResponseException)
            {
                var e = exception as ApiResponseException;
                if(e.StatusCode == 401)
                {
                    // Auth in here gets an exception!
                    Auth(()=>
                    { 
                        FriendsList(state); 
                    });
                }
            }
        }
    });
}

void Auth(Action onFinish)
{
    Task<ISession> sessionTask = client.AuthenticateDeviceAsync(deviceId);
    // continue with gets an exception from FriendsList call!
    sessionTask.ContinueWith((task) =>
    {
        bool success = !(task.IsCanceled || task.IsFaulted);
        if(success)
        {
            onFinish();
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

Error is

System.InvalidOperationException: The current SynchronizationContext may not be used as a TaskScheduler.
  at System.Threading.Tasks.SynchronizationContextTaskScheduler..ctor () [0x00019] in <d7ac571ca2d04b2f981d0d886fa067cf>:0 
  at System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext () [0x00000] in <d7ac571ca2d04b2f981d0d886fa067cf>:0 

We’re also having some threading issues when spamming FriendsList into unity IMGUI, but spammng GuildList never have this problem, might be related to internal FriendsList but we’re not sure

Any ideas on how to fix this?

Thanks!

I literally found the issue after posting the questions,

The problem is we’re missing

TaskScheduler.FromCurrentSynchronizationContext());

from ListFriends call
hope this helps

i think im experienced this same problem but, im not understanding the part where you say that you solve it with this TaskScheduler.FromCurrentSynchronizationContext());

im using too the SynchronizationContext thing due some problems too with friends for display data but im not understanding how to fix it or where i should put TaskScheduler.FromCurrentSynchronizationContext());

can you explain more in deep? thanks

i just noticed that have that on Awake()
unityTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
but then now i cant understand why my friend UI dosnt work anyways thanks for the info.

@PabloMonfort Have you looked into how thread synchronization works in Unity engine? Essentially what TaskScheduler.FromCurrentSynchronizationContext() does is request the awaited Task to be executed on the same synchronization context as the Unity main thread. This can is useful when you have data which you want to update within a Unity UI. There’s a lot more detail to how it all works but thats a simplified answer to it all.

1 Like