我尝试在我的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版本正确地按预期杀死了该线程。
答案 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();
}
}