【问题标题】:AreaDescription.SaveCurrent() freezes Unity's Update loop despite new thread尽管有新线程,AreaDescription.SaveCurrent() 仍会冻结 Unity 的更新循环
【发布时间】:2017-08-23 13:29:59
【问题描述】:

我正在使用 Unity 和 Google Tango 开发应用程序,我的部分代码将区域描述文件 (ADF) 保存在单独的线程中(以便我的 UI 保持响应):

Debug.Log("create thread");
m_saveThread = new Thread(() =>
{
    // Start saving process in another thread.
    Debug.Log("Starting work in thread");
    currentAreaDescription = AreaDescription.SaveCurrent();
    Debug.Log("SaveCurrent completed");
    AreaDescription.Metadata metadata = currentAreaDescription.GetMetadata();
    metadata.m_name = name;
    currentAreaDescription.SaveMetadata(metadata);
});

Debug.Log("Start thread");
m_saveThread.Start();
Debug.Log("thread started");

我的问题是,即使我在新线程中运行保存代码,UI 仍然被冻结,直到 AreaDescription.SaveCurrent() 完成。为了确认这一点,我已将以下打印调用添加到我的Update()

public void Update()
{
    Debug.Log("Update!");
    //...
}

这是我保存时来自adb logcat -s Unity 的摘录:

08-23 15:11:43.746 18474 18518 I Unity   : Update!
08-23 15:11:43.747 18474 18518 I Unity   : Save confirmed!
08-23 15:11:43.747 18474 18518 I Unity   : overlay
08-23 15:11:43.747 18474 18518 I Unity   : create thread
08-23 15:11:43.748 18474 18518 I Unity   : Start thread
08-23 15:11:43.753 18474 18518 I Unity   : thread started
08-23 15:11:43.754 18474 18836 I Unity   : Starting work in thread
08-23 15:11:44.960 18474 18518 I Unity   : Update!
08-23 15:11:44.961 18474 18518 I Unity   : Currently saving!
08-23 15:11:44.964 18474 18836 I Unity   : SaveCurrent completed
08-23 15:11:44.977 18474 18518 I Unity   : Update!

(删除了几行不相关的行)

从时间戳可以看出,在 SaveCurrent() 运行的整个 ~200 毫秒内,Update() 没有被调用。

为什么尽管我在一个新线程中运行了这个繁重的函数,但主线程却被冻结了?我该怎么做才能让它真正在后台运行?

顺便说一句,这段代码几乎是直接从Google's own sample repo改编而来的,我已经为此创建了an issue,目前没有回应。

【问题讨论】:

    标签: c# multithreading unity3d unity5 google-project-tango


    【解决方案1】:

    在找到C API function that gets called under the hood 并阅读其文档后,我发现

    由于 Tango 服务在内部锁定,其他 API 调用(例如 TangoService_getPoseAtTime())将在此方法运行时阻塞。

    确实,我的场景中有其他对象在其Update() 函数中使用 Tango API,并且在编写代码以禁用它们以进行保存后,Unity 不再冻结。

    我只是希望他们会在Tango docs about the Unity function I was using 中提到它。

    【讨论】:

      【解决方案2】:

      在底层,SaveCurrent() 使用 System.Xml.Serialization.XmlSerializer,根据msdn,它是线程安全的。

      但他们使用StreamWriter 对其进行初始化,其中非静态成员不是线程安全的。

      但是有TextWriter.Synchronized可以帮助你。

      仍然不清楚为什么单独的线程会导致 Unity 冻结。我们必须假设 Unity 等待线程完成/不再阻塞。

      你可以尝试扩展 Monobehaviour,看看 Unity 是否停止等待。

      如果这没有帮助,您需要阅读有关 volatile 的信息,并可能查看相关的 answers.unity3d thread

      【讨论】:

        猜你喜欢
        • 2020-10-15
        • 1970-01-01
        • 2021-07-23
        • 2019-04-20
        • 2019-12-14
        • 2019-12-11
        • 1970-01-01
        • 2017-04-09
        • 2023-03-30
        相关资源
        最近更新 更多