在做毕设的时候涉及到了较大数据的读取,每次从硬盘读都会卡很久,于是找资料之后自己做了个简单的多线程解决方案。

一共有两个类。第一个类ThreadJob如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Threading;
public class ThreadJob {
public bool isDone { get {
int val = 1;
Interlocked.CompareExchange(ref val,0, _isDone);
if (val == 0)
return true;
return false;
}
set {
_isDone = value ? 1 : 0;
}
}
private int _isDone;
protected Thread thread; public void Start() {
thread = new Thread(Run);
thread.IsBackground = true;
thread.Start();
} private void Run() {
ThreadFunction();
isDone = true;
} protected virtual void ThreadFunction() { } public IEnumerator WaitTillDone() {
while (!isDone)
yield return null;
}
}

注意的几点:

0. 通过继承ThreadJob,override ThreadFunction()来实现自己的线程。

  1. 主线程直接用构造函数构造一个ThreadJob,然后调用Start()开始运行。自己不断检查isDone来查看线程是否完成。
  2. isDone里使用了.net的原子操作,我不清楚这种写法是否最优。当然也可以直接用lock。
  3. isBackground保证线程会随着主线程的退出而退出。否则主线程退出后该线程不会结束。
  4. WaitTillDone()是一个方便主线程检查isDone的函数。具体使用见后文。

第二个类是ThreadManager,主要用途是子线程向主线程发消息。(比如读取文件的进度等)。因为unity的.net版本没有concurrent容器,这里用的是lock给队列上锁。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class ThreadManager : MonoBehaviour { public static ThreadManager instance {
get {
if (_instance == null) {
_instance = FindObjectOfType<ThreadManager>();
}
return _instance;
}
}
private static ThreadManager _instance; private void Awake() {
_instance = this; //if the first call is used in a thread, it will throw a exception, since sub-thread can't use FindObjectOfType
} private Queue<Action> _callbackQueue = new Queue<Action>(); public void AddThreadCallback(Action callback) {
lock (_callbackQueue) {
_callbackQueue.Enqueue(callback);
}
}
// Update is called once per frame
void Update () {
lock (_callbackQueue) {
while (_callbackQueue.Count > 0) {
_callbackQueue.Dequeue()();
}
}
}
}

要注意的是尽管在instance属性里有FindObjectOfType,但是因为子线程无法使用Unity的函数,所以还是需要在Awake里手动赋值一下。否则如果子线程首先调用了instance属性就会报错。

使用的时候在子线程里调用AddThreadCallback即可。在主线程的下一帧就会调用。

具体使用例子:

    public void ImportTexture() {
var thread = GetReadTextureThread();
thread.Start();
StartCoroutine(ReadMain(thread));
} private IEnumerator ReadMain(ThreadedReadTexture thread) {
yield return thread.WaitTillDone(); //注意这里的用法
var info = thread.GetTexture();
_tex = new Texture3D(info.width, info.height, info.thickness, TextureFormat.RFloat, false);
_tex.SetPixels(info.data);
_tex.Apply();
}

用Threadmanager进行通信,Notify函数由子线程调用:

    public void Notify(string progress) {
ThreadManager.instance.AddThreadCallback(
() => {
SystemController.instance.hint.hintText = progress; //显示一条消息
});
}

[Unity]多线程编程的一点心得的更多相关文章

  1. Java多线程编程作业总结

    一.多线程知识总结 1.线程同步 有关创建线程的知识就不过多的叙述了.就从主要的开始讲吧,讲一下线程的同步.与操作系统中的进程同步一样,线程同样面临着资源共享的问题,怎样处理线程的资源共享是运用多线程 ...

  2. [Java][读书笔记]多线程编程

    前言:最近复习java,发现一本很好的资料,<J​a​v​a​2​参​考​大​全​ ​(​第​五​版​)​> ​ ​H​e​r​b​e​r​t​.Schildt.书比较老了,06年的,一些 ...

  3. windows多线程编程星球(一)

    以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...

  4. Java—多线程编程

    一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程.一个线程不能独立的存 ...

  5. [转]Linux 的多线程编程的高效开发经验

    Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别.不注意这些 Linux 上的一些开发陷阱,常常会导致程序问题不穷,死锁不断.本文中我们 ...

  6. 5天玩转C#并行和多线程编程 —— 第四天 Task进阶

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  7. 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  8. .NET面试题解析(07)-多线程编程与线程同步

      系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实是很多的,比如多线程编程.线程上下文.异步编程.线程同步构造.GUI的跨线程访问等等, ...

  9. Delphi中线程类TThread实现多线程编程1---构造、析构……

    参考:http://www.cnblogs.com/rogee/archive/2010/09/20/1832053.html Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大 ...

随机推荐

  1. Python 零碎信息-基础 02

    1. range xrange 的差别 1.1 range 返回列表对象. 1.2 xrange 返回xrange对象  不需要返回列表里面的值, 节省内存. >>> range(1 ...

  2. 【beta】Scrum站立会议第1次....11.3

    beta阶段,我们nice!团队将进行为期两周的冲刺,Scrum站立会议10次. 小组名称:nice! 组长:李权 成员:于淼  刘芳芳韩媛媛 宫丽君 项目内容:约跑app(约吧) 时间:2016.1 ...

  3. Linux文件传输FTP详解

    ftp命令用来设置文件系统相关功能.ftp服务器在网上较为常见,Linux ftp命令的功能是用命令的方式来控制在本地机和远程机之间传送文件,这里详细介绍Linux ftp命令的一些经常使用的命令,相 ...

  4. 第二部分shell编程2正则(grepegrepsedawk)

    一.grep/egrep 1. 语法+选项语法: grep [-cinvABC] 'word' filename -c :打印符合要求的行数-n :在输出符合要求的行的同时连同行号一起输出 -v :打 ...

  5. mysql+navicat安装小结

    1,mysql到官方下载,navicat下载破解版 2,修改my.ini, 注意,需要手动创建data文件夹, 其中C:\MySql\mysql-5.7.17-winx64是解压mysql的目录 [m ...

  6. matlab padarray

    功能:填充图像或填充数组 使用:B = padarray(A,padsize,padval,direction) A表示输入图像,B是填充后的图像,padsize给出了填充的行数和列数,通常用[r c ...

  7. Qt基本控件及三大布局

    Qt基本控件及三大布局 来源: http://blog.csdn.net/a2604539133/article/details/73920696 Qt基本模块 一.Qt的三大布局 QHBoxLayo ...

  8. 深入理解Delete(JavaScript)

    深入理解Delete(JavaScript) Delete  众所周知是删除对象中的属性. 但如果不深入了解delete的真正使用在项目中会出现非常严重的问题 (: Following 是翻译  ka ...

  9. [CF622F]The Sum of the k-th Powers

    题目大意:给你$n,k(n\leqslant10^9,k\leqslant10^6)$,求:$$\sum\limits_{i=1}^ni^k\pmod{10^9+7}$$ 题解:可以猜测是一个$k+1 ...

  10. 【BZOJ5288】[HNOI2018]游戏(乱搞?)

    [BZOJ5288][HNOI2018]游戏(乱搞?) 题面 BZOJ 洛谷 题面自己到洛谷上看把 题解 考场上乱搞拿到了\(90\)分,简直不敢相信. 回家把代码再交了一份直接就\(AC\)了??? ...