Unity主线程和子线程跳转调用(2)

  在上一篇介绍了多线程和Unity交互方式,但是由于我的项目是一个unity编辑器插件项目,很显然上一篇的代码需要加以修改,在编辑器下实现Loom.

  1,Editor下的没有Update这个生命周期函数,但是Ediitor提供了EditorApplication.update这个事件,自己用这个事件订阅update方法即可

  2,Editor下的没有Awake OnDestory这些生命周期函数,需要自己编写方法让外部去创建、销毁Loom

  3,  我的项目需要保证子线程逻辑不假死的同时又要保证同步,如下面这段伪代码,执行顺序为:DownFile1->UnityFunction1->DownFile2->UnityFunction2

  

Function
{
    //异步在多线程下运行
    Loom.RunAsync(() =>
    {
        //耗时函数
        DownFile1();

        //回到unity线程继续运行
        Loom.QueueOnMainThread(()=>
        {
            //这个函数是unity函数
            UnityFunction1();
        }

        //耗时函数
        DownFile2();
         //回到unity线程继续运行
        Loom.QueueOnMainThread(()=>
        {
            //这个函数是unity函数
            UnityFunction2();
        }

    }
}

  

  修改后的代码如下

  1 using UnityEngine;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System;
  5 using System.Threading;
  6 using System.Linq;
  7 using UnityEditor;
  8 public class Loom
  9 {
 10     /// <summary>
 11     /// 当前是否有unity任务需要执行
 12     /// </summary>
 13     static bool hasUnityAction = true;
 14
 15     private static Thread loomThread;
 16
 17     /// <summary>
 18     /// unity任务表
 19     /// </summary>
 20     private List<Action> actions = new List<Action>();
 21
 22     #region 单例 注册update事件
 23     private static Loom _instance;
 24     private static readonly object lockObj = new object();
 25     public static Loom Current
 26     {
 27         get
 28         {
 29             if (_instance == null)
 30             {
 31                 lock (lockObj)
 32                 {
 33                     if (_instance == null)
 34                     {
 35                         _instance = new Loom();
 36                     }
 37
 38                 }
 39             }
 40             return _instance;
 41         }
 42     }
 43     private Loom()
 44     {
 45         EditorApplication.update += Update;
 46
 47     }
 48     #endregion
 49
 50
 51
 52
 53     /// <summary>
 54     /// 子线程启动一个任务
 55     /// </summary>
 56     /// <param name="a"></param>
 57     /// <returns></returns>
 58     public Thread RunAsync(Action a)
 59     {
 60         if (loomThread != null)
 61         {
 62             Stop();
 63             throw new Exception("任务仅运行一次");
 64         }
 65         loomThread = new Thread(new ParameterizedThreadStart(RunAction));
 66         loomThread.Name = "Loom线程";
 67         loomThread.Priority = System.Threading.ThreadPriority.Lowest;
 68         loomThread.Start(a);
 69         return loomThread;
 70     }
 71     /// <summary>
 72     /// 加入一个任务到主线程队列
 73     /// </summary>
 74     /// <param name="action"></param>
 75     public void QueueOnMainThread(Action action)
 76     {
 77         if (Current != null && Thread.CurrentThread == loomThread)
 78         {
 79             hasUnityAction = true;
 80             lock (Current.actions)
 81             {
 82                 Current.actions.Add(action);
 83             }
 84             while (hasUnityAction)
 85             {
 86                 loomThread.Priority = System.Threading.ThreadPriority.Lowest;
 87                 Thread.Sleep(10);
 88             }
 89         }
 90
 91     }
 92
 93     /// <summary>
 94     /// 延迟子线程
 95     /// </summary>
 96     /// <param name="time"></param>
 97     public void Sleep(int time)
 98     {
 99         if (Current != null && Thread.CurrentThread == loomThread)
100         {
101             Thread.Sleep(time);
102
103         }
104     }
105
106     /// <summary>
107     /// 停止任务
108     /// </summary>
109     public void Stop()
110     {
111         EditorApplication.update -= Update;
112         try
113         {
114             loomThread.Abort();
115         }
116         catch (Exception e)
117         {
118             Debug.Log(e.ToString());
119         }
120         finally
121         {
122             loomThread = null;
123             _instance = null;
124         }
125
126     }
127
128
129
130     private void RunAction(object action)
131     {
132         try
133         {
134             ((Action)action)();
135         }
136         catch
137         {
138         }
139
140     }
141
142     List<Action> _currentActions = new List<Action>();
143
144     static void Update()
145     {
146         try
147         {
148
149
150             if (!hasUnityAction) return;
151
152             lock (Current.actions)
153             {
154                 Current._currentActions.Clear();
155                 Current._currentActions.AddRange(Current.actions);
156                 Current.actions.Clear();
157             }
158             for (int i = 0; i < Current._currentActions.Count; i++)
159             {
160                 Debug.LogError("主线程任务");
161                 Current._currentActions[i]();
162
163             }
164             hasUnityAction = false;
165         }
166         catch
167         {
168             Debug.LogError("主线程任务失败");
169         }
170     }
171 }

原文地址:https://www.cnblogs.com/ferryqiu/p/8434762.html

时间: 2024-11-09 18:51:20

Unity主线程和子线程跳转调用(2)的相关文章

C++拾遗--多线程:主线程与子线程的同步

C++拾遗--多线程:主线程与子线程的同步 前言 在多线程编程时,有时是需要要求主线程与子线程同步的. 正文 程序演示 下面的一个例子,演示了主线程与子线程之间的同步问题. 程序描述: 在主线程中,有一整型变量count,初始化为0.主线程把count的地址传递给开启的子线程,子线程打印获取的值,随后主线程递增count的值,再次开启另一个子线程,传递count的地址-- #include <stdio.h> #include <stdlib.h> #include <pro

Java实现主线程等待子线程

本文介绍两种主线程等待子线程的实现方式,以5个子线程来说明: 1.使用Thread的join()方法,join()方法会阻塞主线程继续向下执行. 2.使用Java.util.concurrent中的CountDownLatch,是一个倒数计数器.初始化时先设置一个倒数计数初始值,每调用一次countDown()方法,倒数值减一,他的await()方法会阻塞当前进程,直到倒数至0. join方式代码如下: [java] view plain copy package com.test.thread

C#主线程等待子线程运行结束

佐左佑右 原文 C#主线程等待子线程运行结束 由于主程序中调用matlab的dll文件进行计算要用较长的时间,主界面会有很长时间的卡顿,造成的用户感受十分不好,因此我想在调用时,将调用放入子线程中,然后在主线程中弹出一个提示框,显示数据正在加载,等子线程运行结束后,主线程继续工作. 使用的是http://hi.baidu.com/oktell/item/5527f51d93abb4a5feded5a8中所提到的方法,用了这篇文章中的第一个方式,即不带参数的. 之后在其中加入了显示和关闭提示框的代

Android 使用handler实现线程间发送消息 (主线程 与 子线程之间)、(子线程 与 子线程之间)

keyword:Android 使用handler实现线程间发送消息 (主线程 与 子线程之间).(子线程 与 子线程之间) 相信大家平时都有使用到异步线程往主线程(UI线程)发送消息的情况. 本文主要研究Handler的消息发送. 包含主线程往子线程发送消息,子线程之间互相发送消息. 一.主线程向子线程发送消息. 实现过程比較简单: 主线程发送消息到异步线程.异步线程接收到消息后在再发送一条消息给主线程. 1. 初始化主线程的Handler,用来接收子线程的消息. 2. 启动异步线程.在异步线

Android主线程、子线程通信(Thread+handler)

Android是基于Java的,所以也分主线程,子线程! 主线程:实现业务逻辑.UI绘制更新.各子线程串连,类似于将军: 子线程:完成耗时(联网取数据.SD卡数据加载.后台长时间运行)操作,类似于小兵: 一.子线程向主线程发消息(Thread+handler): 1.主线程中定义Handler: Java代码   Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.h

第一章、主线程与子线程

第一章.主线程与子线程 但我们打开FBReader程序的一刻,代码会立即创建一个子线程.之后,主线程会负责在屏幕上显示一个进度条,而子线程则在后台开始读取epub文件. PS:进度条的样子如下图所示,不过由于加载速度很快,这进度条都是一闪而过的.这张图片是在单步调试的环境下截取的. 在这一章,我们将详细介绍,程序如何创建子线程,以及如何控制进度条的显示与消失. 本章涉及的核心类是UIUtil类. FBReader默认首先进入的FBReader类,这是在AndroidManifes.xml设定的.

(转)C#/.NET主线程与子线程之间的关系

一般 一个应用程序就对应一个进程,一个进程可有一个或多个线程,而一般有一个主线程. 有的博客上说“至少一个主线程”,这一说法持有怀疑         主线程与子线程之间的关系         **默认情况,在新开启一个子线程的时候,他是前台线程,只有,将线程的IsBackground属性设为true;他才是后台线程         *当子线程是前台线程,则主线程结束并不影响其他线程的执行,只有所有前台线程都结束,程序结束         *当子线程是后台线程,则主线程的结束,会导致子线程的强迫结

Qt之主线程与子线程通信(linux下)

转载请注明出处:http://blog.csdn.net/feng1790291543  主线程与子线程通信主要是通过Qt上的G ui按钮,触发使得主线程上的信息发送到子线程中,并且时刻监测线程的运行情况 主线程,头文件: #ifndef MANAGEWIDGET_H #define MANAGEWIDGET_H #include <QtGui/QWidget> #include <QtCore> //#include "childwidget.h" //#in

设置主线程等待子线程执行的方法

首先要注意的是: 1.java的Main线程结束之后,子线程还在运行.其实主线程已经退出了,但是JVM守护线程会等待所有的线程结束,才会退出.所以我们可以看到,子线程依然在继续执行. 2.那么如何实现主线程等待子线程的执行之后再结束,这个就要用到CountDownLatch,设置要执行的线程的个数,然后再子线程的run方法中调用countDown()的方法,递减线程的计数.在主线程结束之前,调用await()的方法,一直等待. 实现如下: public class Main extends Th