AreaDescription.SaveCurrent() 冻结 Unity 的更新循环,尽管有新线程

AreaDescription.SaveCurrent() freezes Unity's Update loop despite new thread

我正在使用 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 and I have created an issue关于它的,目前没有回应。

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

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

但是TextWriter.Synchronized可以帮到你。

为什么单独的线程会导致 Unity 冻结仍然不明显。我们必须假设 Unity 等待线程 finish/not 阻塞了。

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

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

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

Since the Tango Service locks internally, other API calls (such as TangoService_getPoseAtTime()) will block while this method is running.

事实上,我的场景中还有其他对象在它们的 Update() 函数中使用了 Tango API,并且在编写代码以在保存时禁用它们之后,Unity 不再冻结.

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