Rather than providing my IHttpService.JsonPost method with callbacks I decided to have it return a Promise, the code for which I took from this Real Serious Games GitHub repository.
The problem is that when you use WebClient’s async methods they call back the Complete events on the worker thread, so code like this won’t work because you cannot manipulate UI from any thread other than the main one.
httpService.JsonPost<MyInfo>(url)
.Then(myInfo => someTextUiObject.text = myInfo.Name);
And there seems to be no kind of thread Dispatcher in Unity3D for UI updates as there is in Windows.Forms – so I wrote my own.
using System.Collections;
using System;
using System.Threading;
using System.Collections.Generic;
using UnityEngine;
public class UiThreadDispatcher : Singleton<MonoBehaviour>
{
static volatile int lockValue = 0;
static Queue<Action> actionQueue = new Queue<Action>();
void Awake()
{
StartCoroutine(CheckForDispatchedActions());
}
public static void Dispatch(Action action)
{
Lock();
actionQueue.Enqueue(action);
Unlock();
}
static void Lock()
{
while (Interlocked.Exchange(ref lockValue, 1) != 0) { }
}
static void Unlock()
{
lockValue = 0;
}
private IEnumerator CheckForDispatchedActions()
{
while (true)
{
Action action = null;
Lock();
try
{
while (actionQueue.Count > 0)
{
action = actionQueue.Dequeue();
action();
}
}
catch (Exception unexpectedException)
{
Debug.LogException(unexpectedException);
}
finally
{
Unlock();
}
yield return null;
}
}
}
//Instead of this
httpService.JsonPost<MyInfo>(url)
.Then(myInfo => someTextUiObject.text = myInfo.Name);
//You would do this
httpService.JsonPost<MyInfo>(url)
.Then(myInfo => UiThreadDispatcher.Dispatch(() => > someTextUiObject.text = myInfo.Name));
Comments