带有Unity的Google Daydream主题

时间:2017-06-30 00:06:26

标签: c# android multithreading unity3d daydream

我尝试在我的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()函数继续循环,但是thread.IsAlive继续声明线程处于活动状态,当我理解它已经停止运行时。如果我退出运行此脚本的场景,线程将死亡,脚本会按预期继续运行,但是当我留在场景中时它不会死。我不知道为什么。

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

任何有助于诊断事情的帮助都会很棒。由于重新创建问题所需的代码,场景和平台的规模,很难发布MWE。(抱歉)。

更新:更改了我的Windows代码,以便更紧密地复制Android版本。现在可以确认这是一个Android / Daydream问题,而不是在场景之间切换'问题。 Windows版本正确地按预期杀死了该线程。

2 个答案:

答案 0 :(得分:0)

我建议将虚拟更新公开,但由于我们没有看到代码,所以很难看到你在这里尝试做什么。你也可以用isAlive!= true做while循环。但取决于你的程序可能不是一个好主意。

答案 1 :(得分:0)

首先关闭:使用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
        }
    }
}

或者,您可以保持Run-thread等待,直到Update向其传递信号。

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();
    }
}