[Unity]多线程编程的一点心得
在做毕设的时候涉及到了较大数据的读取,每次从硬盘读都会卡很久,于是找资料之后自己做了个简单的多线程解决方案。
一共有两个类。第一个类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()来实现自己的线程。
- 主线程直接用构造函数构造一个ThreadJob,然后调用Start()开始运行。自己不断检查isDone来查看线程是否完成。
- isDone里使用了.net的原子操作,我不清楚这种写法是否最优。当然也可以直接用lock。
- isBackground保证线程会随着主线程的退出而退出。否则主线程退出后该线程不会结束。
- 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]多线程编程的一点心得的更多相关文章
- Java多线程编程作业总结
一.多线程知识总结 1.线程同步 有关创建线程的知识就不过多的叙述了.就从主要的开始讲吧,讲一下线程的同步.与操作系统中的进程同步一样,线程同样面临着资源共享的问题,怎样处理线程的资源共享是运用多线程 ...
- [Java][读书笔记]多线程编程
前言:最近复习java,发现一本很好的资料,<Java2参考大全 (第五版)> Herbert.Schildt.书比较老了,06年的,一些 ...
- windows多线程编程星球(一)
以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...
- Java—多线程编程
一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程.一个线程不能独立的存 ...
- [转]Linux 的多线程编程的高效开发经验
Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别.不注意这些 Linux 上的一些开发陷阱,常常会导致程序问题不穷,死锁不断.本文中我们 ...
- 5天玩转C#并行和多线程编程 —— 第四天 Task进阶
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- .NET面试题解析(07)-多线程编程与线程同步
系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实是很多的,比如多线程编程.线程上下文.异步编程.线程同步构造.GUI的跨线程访问等等, ...
- Delphi中线程类TThread实现多线程编程1---构造、析构……
参考:http://www.cnblogs.com/rogee/archive/2010/09/20/1832053.html Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大 ...
随机推荐
- LintCode-159.寻找旋转排序数组中的最小值
寻找旋转排序数组中的最小值 假设一个旋转排序的数组其起始位置是未知的(比如0 1 2 4 5 6 7 可能变成是4 5 6 7 0 1 2). 你需要找到其中最小的元素. 你可以假设数组中不存在重复的 ...
- Window命令行工具操作文件
1,cd 命令用来切换目录 2,mkdir用来创建文件夹 3,rmdir用来删除空文件夹 4,创建指定类型的文件 type nul>"文件名和后缀" 5,打开指定文件用sta ...
- Sass的命令编译
[Sass]命令编译 命令编译是指使用你电脑中的命令终端,通过输入 Sass 指令来编译 Sass.这种编译方式是最直接也是最简单的一种方式.因为只需要在你的命令终端输入: 单文件编译: sass & ...
- C# 知识回顾 - 表达式树 Expression Trees
C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...
- 内存交换空间(swap)的构建
一.使用物理分区构建swap 1.先进行分区的行为. [root@iZ255cppmtxZ ~]# fdisk /dev/xvdb Welcome to fdisk (util-linux ). Ch ...
- WPF中DataGrid的应用-绑定,增改删,分页,样式
参考以下网址: http://www.cnblogs.com/fwbnet/archive/2012/05/08/2490974.html
- 【刷题】BZOJ 4516 [Sdoi2016]生成魔咒
Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例 ...
- 2018牛客多校第五场 E.room
题意: 一共有n个宿舍,每个宿舍有4个人.给出第一年的人员分布和第二年的人员分布,问至少有多少人需要移动. 题解: 对于第一年的每个宿舍,向今年的每种组合连边.流量为1,费用为(4 - 组合中已在该宿 ...
- POJ1474:Video Surveillance——题解
http://poj.org/problem?id=1474 题目大意:给按照顺时针序的多边形顶点,问其是否有内核. —————————————————————————————— (和上道题目一模一样 ...
- BZOJ1016:[JSOI2008]最小生成树计数——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1016 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不 ...