c# - Unity3D,如何在正确的线程中处理事件

标签 c# multithreading unity3d

我正在编写 Unity3D 脚本并使用网络库。当数据准备好时,库会发出事件(调用委托(delegate))。我的图书馆读取该数据并发出尝试访问 GameObject 的事件但是我得到了这些错误

CompareBaseObjectsInternal can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread 
when loading a scene. Don't use this function in the constructor or field 
initializers, instead move initialization code to the Awake or Start function.

ArgumentException: CompareBaseObjectsInternal can only be called from the main 
thread. Constructors and field initializers will be executed from the loading 
thread when loading a scene. Don't use this function in the constructor or field 
initializers, instead move initialization code to the Awake or Start function.

没关系。我想我明白网络消息是在一个单独的线程上处理的,Unity3D 正试图指出这一点,以及从另一个线程操作东西是如何不线程安全的。

我的问题是:推荐的处理方法是什么?

我想的不是直接在我的处理程序中调用委托(delegate),而是创建某种对象来引用事件中传递的所有参数并将它们添加到 List<MyEvent> 中。的事件。

我必须创建一个线程安全的包装类来包含该列表,该列表允许我使用锁添加和删除事件,因为 List<>不是线程安全的。

然后我将以某种方式需要在主线程上处理这些事件。我不确定最好的方法是什么。处理网络的类是 MonoBehavior本身所以我想我可以拥有它的Update方法从列表中删除事件并发送它们。

这听起来是个好主意还是有其他更好或更简单的方法来实现这一目标?

最佳答案

这是我最终得到的结果。

public class EventProcessor : MonoBehaviour {

    public void QueueEvent(Action action) {
        lock(m_queueLock) {
            m_queuedEvents.Add(action);
        }
    }

    void Update() {
        MoveQueuedEventsToExecuting();

        while (m_executingEvents.Count > 0) {
            Action e = m_executingEvents[0];
            m_executingEvents.RemoveAt(0);
            e();
        }
    }

    private void MoveQueuedEventsToExecuting() {
        lock(m_queueLock) {
            while (m_queuedEvents.Count > 0) {
                Action e = m_queuedEvents[0];
                m_executingEvents.Add(e);
                m_queuedEvents.RemoveAt(0);
            }
        }
    }

    private System.Object m_queueLock = new System.Object();
    private List<Action> m_queuedEvents = new List<Action>();
    private List<Action> m_executingEvents = new List<Action>();
}

其他一些类中的启动代码将其中之一添加到启动它的 GameObject。网络线程通过调用 eventProcessor.queueEvent 添加 Action,上面的 Update 函数最终在主线程上执行这些操作。我将所有操作拉到另一个队列,以尽可能少地锁定事物。

我想这并不难。我只是想知道是否还有其他推荐的解决方案。

关于c# - Unity3D,如何在正确的线程中处理事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22513881/

相关文章:

c# - 这是唯一指向无法访问标签的可访问 goto 的情况吗?

c# - Windows窗体中的线程

c# - unity GetComponent<Type> 返回值

c# - 即使有私有(private)字段也强制使用私有(private)属性(property)?

c# - CaSTLe Windsor 依赖注入(inject),基于客户的自定义实现

c# - LINQ to XML XElement 节点

Java 线程 - 同步代码

multithreading - 为什么在仿真的 ubuntu 中使用 theora 编码时 2 个线程比 1 个慢?

android - 无法将模块添加到已安装的 Unity 编辑器

c# - 如何返回状态代码 401 以及一些附加数据?