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

一共有两个类。第一个类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简介与Python基础

    前言:<Data Wrangling with Python>这本书主要是讲使用Pyhon来处理各种类型保存的数据的. 第一章:Python简介 1.版本选择 本书选择的Python版本是 ...

  2. win7系统日志分支删除方法

    这篇日志有问题,自己亲身尝试失败,这里只提供思路,谢谢(改天突破再做修改) 之前电脑装过德国的叫啥子软件来着,当时在系统自动创建了日志,后来软件卸载了,发现还是有这个日志主键,(我有强迫症)心里不爽, ...

  3. sublime text 3103 怎么设置中文

    1.shift+ctrl+p调出插件管理,输入install package,按enter键,开始安装. 2.搜索chinese即可,下载安装插件包即可 原文:http://blog.csdn.net ...

  4. array_intersect_assoc 与array_intersect区别

    1.array_intersect_assoc — 带索引检查计算数组的交集 说明 array array_intersect_assoc ( array $array1 , array $array ...

  5. js获取某周、某月、下月、某季度的开始日期、结束日期及判断日期第几周

    //格式化日期:yyyy-MM-dd function formatDate(date) {   var myyear = date.getFullYear();   var mymonth = da ...

  6. python数据类型二

    阅读目录 1.列表的去嵌套 2.元组 3.range 列表的增删改查 一,增: 注意  list和str是不一样的,lst可以发生改变,所以直接就在原来的对象上进行可操作 追加模式 lst = ['麻 ...

  7. [socket编程] 一个服务器与多个客户端之间通信

    转自:http://blog.csdn.net/neicole/article/details/7539444 并加以改进 Server程序: // OneServerMain.cpp #includ ...

  8. Codeforces633H-Fibonacci-ish II

    题目 斐波那契数列\(f\),\(f\_1=f\_2=1,\ f\_n=f\_{n-1}+f\_{n-2}\ (n>2)\). 给定长度为\(n\ (n\le 30000)\)的数列\(a\), ...

  9. bzoj3998-弦论

    给定一个长度为\(n(n\le 5\times 10^5)\)的字符串,求它的第\(k\)小字串.有两种模式: \(Type=0\),不同位置的相同字串只算一个 \(Type=1\),不同位置相同字串 ...

  10. java 读写文件乱码问题

    这样写,会出现乱码.原因是文件时gbk格式的, BufferedReader br = new BufferedReader(new FileReader(indir)); BufferedWrite ...