//============================================================================================================================= // // Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved. // EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China // and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd. // //============================================================================================================================= using System; using System.Collections.Generic; using System.Threading; using UnityEngine; namespace easyar { /// /// Thread worker, to do async tasks in worker thread. All tasks pushed into the worker are ensured to finish before the worker dispose. /// 线程工作器,负责在工作线程上处理异步任务。所有推送到工作器的任务会被保证在销毁前运行。 /// public class ThreadWorker : IDisposable { private Thread thread; private bool finished; private Queue queue = new Queue(); ~ThreadWorker() { Finish(); } /// /// Dispose resources. /// 销毁资源。 /// public void Dispose() { Finish(); GC.SuppressFinalize(this); } /// /// Run in worker thread. /// 在工作线程上运行任务 /// public void Run(Action task) { if (thread == null) { CreateThread(); } Monitor.Enter(queue); try { if (finished) { return; } queue.Enqueue(task); Monitor.PulseAll(queue); } finally { Monitor.Exit(queue); } } private void CreateThread() { thread = new Thread(() => { while (!finished) { Action task = null; Monitor.Enter(queue); try { while (!finished && queue.Count == 0) { Monitor.Wait(queue); } if (queue.Count > 0) { task = queue.Dequeue(); } } finally { Monitor.Exit(queue); } if (task != null) { try { task(); } catch (Exception ex) { Debug.LogError(ex.ToString()); } } if (finished) { while (queue.Count > 0) { task = queue.Dequeue(); if (task != null) { try { task(); } catch (Exception ex) { Debug.LogError(ex.ToString()); } } } } } }); thread.Start(); } private void Finish() { if (thread == null || !thread.IsAlive) { return; } Monitor.Enter(queue); try { finished = true; Monitor.PulseAll(queue); } finally { Monitor.Exit(queue); } thread.Join(); } } }