首页 > 代码库 > unity3D中协程和线程混合
unity3D中协程和线程混合
这是我google unity3D一个问题偶然发现的在stackflow上很有趣的帖子:
大意是 要在unity3D上从服务器下载一个zip,并解压到持久化地址.并将其加载到内存中.下面展示了这种用法:
IEnumerator LongCoroutine()
{
yield return StartCoroutine(DownloadZip());
ExtractZip();
yield return StartCoroutine(LoadZipContent());
}
但是ExtractZip()方法是同步的,这将挂起进程.结果是无论如何试图解压zip,进程将会被杀死.我认为是主线程太久没有响应,所以被os杀死.
所以我猜想将提取zip放在单独线程可能会解决问题,而且看起来这样奏效了.我写了这样一个类:
public class ThreadedAction
{
public ThreadedAction(Action action)
{
var thread = new Thread(() => {
if(action != null)
action();
_isDone = true;
});
thread.Start();
}
public IEnumerator WaitForComplete()
{
while (!_isDone)
yield return null;
}
private bool _isDone = false;
}
如此用它:
IEnumerator LongCoroutine()
{
yield return StartCoroutine(DownloadZip());
var extractAction = new ThreadedAction(ExtractZip);
yield return StartCoroutine(extractAction.WaitForComplete());
yield return StartCoroutine(LoadZipContent());
}
但是我仍旧不确定这是不是最好的解决办法.我是否需要锁定_isDone(not too used to multithreading).
楼主已经给出解决方法了,原来在球完美之道,哈哈.
下面的跟帖是:
这真是在协程里糅合多线程的优雅方案.做得好!
Mixing coroutines and threads is perfectly safe, provided you correctly lock access to resources shared between your main thread (which the coroutine executes on) and the worker thread(s) you create. You shouldn‘t need to lock _isDone in any way, since it‘s only ever written to by the worker thread and there‘s no intermediate state that could cause the main thread to misbehave.
混合协程和线程是完全线程安全的,它为了正确锁定主线程(协程所在的)和工作线程(可能多个)的共享资源.你不需要锁定_isDone.因为它只会在工作线程中写,没有交替状态会引起主线程误解.
你需要注意的潜在问题是,如果任何资源被ExtractZip写入,并且
1.同时在主线程里的一个函数写入
2.或者在主线程被读取,只有在ExtracrZip完成后才是线程安全的.
In this particular case, my worry would be that if you don‘t check that you‘re not trying to download the same file to the same location twice, you could have two threads simultaneously running ExtractZip that interfere with one another.
特别情况是,我担心如果你不去检测你不会试图下载同一个文件到同一个位置两次,你可以有两个线程并行运行在ExtractZip.