如何在不使用 Unity 协程的情况下在主线程上执行 运行 函数

How to run functions on main thread without using Coroutine in Unity

我看过一些关于在主线程上使用协程 运行 函数的文章,例如 Thread Ninja:

 IEnumerator StartExamples()
{
    //Jump to main thread
    yield return Ninja.JumpToUnity; 

    Destroy(someGameObject); //OK

    //Jump back to background thread
    yield return Ninja.JumpBack;  
}

它对我的代码不起作用,因为我想从套接字侦听器跳转到主线程。

 SocketIOClient.Client socket;

 IEnumerator StartExamples()
 {
    socket.On("connect", (fn) =>
    {
        WriteLine("\r\nConnected event...\r\n");

        //Jump to main thread
        yield return Ninja.JumpToUnity; //ERROR: couldn't do a yield return 

        Destroy(someGameObject); 

        //Jump back to background thread
        yield return Ninja.JumpBack;  //ERROR: couldn't do a yield return 
    });
 }

那么我们有什么解决方法吗?我希望我能像这样跳转到主线程:

 Dispatcher.BeginInvoke(() =>
{
    //Unity API
    Destroy(gameObject);
});

根据我的评论,使用 uPromise;

class Example
{
    private Promise BeginSocketConnection()
    {
        Deferred retPromise = new Deferred();

        socket.On("connect", (fn) =>
        {
            // We're no longer on the main thread ):
            // But we can resolve our promise!
            retPromise.Resolve();
        });

        return retPromise;
    }

    private void SocketConnectedSuccessfully()
    {
       // Executing on main thread
    }

    private void Start()
    {
        // We start in the main thread
        BeginSocketConnection().Done(x =>
        {
            SocketConnectedSuccessfully();
        });
    }
}

这不允许您在同一个代码块内的线程之间跳转,但通过使用回调系统,您可以提醒主线程执行一个操作,而无需启动杂乱的协程并在各处产生。更易于查看和维护。

我最终使用了一个非常有用的扩展,叫做 Unity Thread Helper。它是免费的,足以满足我的需要!

这是用法:

 UnityThreadHelper.Dispatcher.Dispatch(() =>
        {
            Destroy(a);

        });

注意:Dispatcher 是一个单例对象,它将在您第一次调用时被初始化。您必须在主线程上进行第一次调用,因为它使用了一些 Unity API.

 private void Start()
{
    var ugly = UnityThreadHelper.Dispatcher;
}

希望对您有所帮助!

如果你不想使用其他评论中提到的uPromise和Unity Thread Helper等扩展,也不想使用MonoBehavior的协程,你也可以使用SynchronizationContext:

// On main thread, during initialization:
var syncContext = System.Threading.SynchronizationContext.Current;

// On socket listener thread
syncContext.Post(_ =>
{
    // This code here will run on the main thread
    Destroy(gameObject);
}, null);