如何在Unity中不使用协程而在主线程上运行函数

问题描述 投票:0回答:4

我看过一些关于使用协程在主线程上运行函数的文章,例如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);
});
c# multithreading unity-game-engine mono
4个回答
4
投票

根据我的评论,使用 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();
        });
    }
}

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


4
投票

如果你不想使用扩展,比如其他评论中提到的 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);

3
投票

我最终使用了一个非常有用的扩展,称为“Unity Thread Helper”。它是免费的,足以满足我的需要! 这是用法:

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

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

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

希望这有帮助!


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.