Google Daydream Thread with Unity



我正在尝试在我的Unity项目中使用线程,该项目正在部署在Android手机上,以便与Google Daydream VR系统一起使用。我遇到了一个问题,线程没有像我预期的那样死亡。

我正在创建一个如下所示的线程,并为其分配一个在"活着"时运行的函数。当发生特定操作时(在我的情况下,UDP 网络出现故障(,线程应该停止执行并死亡。但是,线程停止执行其功能,但不会死亡。

Thread thread;
private void Update()
{
    if (!thread.IsAlive)
    {
        // Create a new thread.
    }
}
public void createNewThread()
{
    thread = new Thread(Run);
    thread.Priority = System.Threading.ThreadPriority.BelowNormal;
    thread.Start();
}
void Run()
{
    // Do thread task.
}

在上面的示例中,线程被创建,并在 Run(( 中运行其任务。当操作发生时,在 Run(( 中途停止其任务,并且不会再次进入。Update(( 函数继续循环,但线程。IsAlive继续声明线程是活动的,据我了解它已停止运行。如果我退出运行此脚本的场景,线程将死亡,脚本将按预期继续,但当我留在场景中时,它不会死亡。我不知道为什么。

与此几乎相同的代码已经在Windows机器上进行了测试,在Unity中运行,并且它完全按照我的预期工作,这使我相信这可能是Android/Daydream问题。

任何有助于诊断正在发生的事情都会很棒。由于重现问题所需的代码、场景和平台的规模,很难发布 MWE(抱歉(。

更新:更改了我的Windows代码以更接近地复制Android版本。现在可以确认这是Android/Daydream问题,而不是"场景之间切换"问题。Windows版本按预期正确终止了线程。

我建议将无效更新公开,但由于我们看不到代码,因此很难看到您在这里尝试做什么。 你也可以做 while 循环与 isAlive != 真。但根据您的程序,这可能不是一个好主意。

首先:使用 IsBackground 告诉 .Net 在应用程序退出时关闭线程。

thread = new Thread(Run);
thread.Priority = System.Threading.ThreadPriority.BelowNormal;`
thread.IsBackground = true;
thread.Start();

当线程退出示例中的 Run 时,它将死亡。我不确定为什么你没有看到这个,但我建议查看 Run 中的代码是否有任何阻塞。执行此操作的一个好方法是附加Visual Studio调试器,冻结程序并转到Debug->Windows->Parallel Stacks。它将为您提供线程及其堆栈的可视化表示形式。

启动线程会产生大量开销。空闲线程几乎没有开销。从外观上看,您可以从不同的方法中受益。您基本上每次完成时都尝试重新启动线程。

using UnityEngine;
using System.Threading;
public class Test : MonoBehaviour
{
    private Thread _thread;
    void Start()
    {
        _thread = new Thread(Run);
        _thread.Name = "DaydreamThread";
        _thread.Priority = System.Threading.ThreadPriority.BelowNormal;
        _thread.IsBackground = true;
        _thread.Start();
    }
    private void Run()
    {
        try
        {
            // Endless loop
            for (;;)
            {
                // Do your stuff
            }
        }
        catch (ThreadAbortException)
        {
            // If you expect to do a Abort() on the thread then you want to
            //  ignore this exception
        }
    }
}

或者,您可以让运行线程等待,直到更新向其传递信号。

using UnityEngine;
using System.Threading;
public class Test : MonoBehaviour
{
    private Thread _thread;
    private ManualResetEvent _signal = new ManualResetEvent(false);
    void Start()
    {
        _thread = new Thread(Run);
        _thread.Name = "DaydreamThread";
        _thread.Priority = System.Threading.ThreadPriority.BelowNormal;
        _thread.IsBackground = true;
        _thread.Start();
    }
    private void Run()
    {
        try
        {
            // Endless loop
            for (;;)
            {
                // Wait for a signal to do another pass
                _signal.WaitOne();
                _signal.Reset();

                // Do your stuff
            }
        }
        catch (ThreadAbortException)
        {
            // If you expect to do a Abort() on the thread then you want to
            //  ignore this exception
        }
    }
    void Update()
    {
        if (something)
            // Signal Run-thread to do another pass
            _signal.Set();
    }
}

最新更新