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 中提到它。
我正在使用 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 中提到它。