简体   繁体   中英

Google Daydream Thread with Unity

I'm attempting to use threads in my Unity project which is being deployed on an Android phone for use with the Google Daydream VR system. I'm having an issue where the thread isn't dying as I would expect it to.

I'm creating a thread like that seen below, and assigning it a function to run while 'alive'. When a specific action occurs (in my case, a UDP network goes down), the thread should stop performing and die. However, the thread stops performing its function but isn't dying.

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.
}

In the example above, the thread is created, and runs its task within Run(). When the action occurs, is stops midway through its task within Run() and doesn't enter again. The Update() function continues to loop, but thread.IsAlive continues to state that the thread is alive, when it's my understanding it has ceased operation. If I exit the scene that this script is running within, the thread dies and the script continues as expected, but it won't die while I stay within the scene. I have no idea why.

Almost identical code to this has been tested on a Windows machine, running within Unity, and it works exactly as I expect, which is making me believe this could be an Android/Daydream issue.

Any help in diagnosing what's going on would be great. It's hard to post a MWE due to the scale of the code, scenes, and platform required to recreate the issue (sorry).

UPDATE: Changed my Windows code to replicate the Android version even closer. Can now confirm this is an Android/Daydream issue and not a 'switching between scenes' issue. The Windows version correctly killed the thread as expected.

I would suggest making the void Update Public but it is very hard to see what you are trying to do here since we don't see the code. you could also do while loop with isAlive != true. But depending on your program that might not be a good idea.

First off: Use IsBackground to tell .Net to shut down the thread when application exits.

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

When the thread exits Run in your example it will die. I'm not sure why you are not seeing this, but I suggest looking at the code inside Run if anything is blocking. A good way to do this is to attach Visual Studio debugger, freeze program and go to Debug->Windows->Parallel Stacks. It will give you a visual representation of threads and their stacks.

Starting a thread has a lot of overhead. Idling a thread has near no overhead. From the look of it you could benefit from a different approach. You are basically trying to restart the thread every time it finishes.

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
        }
    }
}

Alternatively you can keep the Run-thread waiting until Update passes it a signal.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM