C# 线程导致应用程序在iOS上延迟,但在Android上没有
我正在为iOS和Android构建Unity3D人脸检测应用程序。该应用程序应该每秒检测10张脸。但是,每次人脸检测大约需要50毫秒,因此我决定让人脸检测在另一个线程的后台运行,以防止出现小的延迟峰值(应用程序需要每帧更新一次视觉内容,50毫秒的停止会使其延迟) 问题是线程导致应用程序在iOS上滞后。不穿线时,它用于每秒检测10个面,现在穿线时检测2个面。。它在Android上运行良好 奇怪的是,该应用程序在iOS上的前5秒运行良好。不管它是否检测到人脸,5秒后会出现严重的延迟。编辑:如果我暂停应用程序,然后恢复它的滞后消失了5秒,就像在开始。这是什么 下面是一个处理人脸检测的协同程序,它每秒运行10次。如果人脸检测线程未在100毫秒内完成,则会阻止另一个线程启动C# 线程导致应用程序在iOS上延迟,但在Android上没有,c#,ios,multithreading,opencv,unity3d,C#,Ios,Multithreading,Opencv,Unity3d,我正在为iOS和Android构建Unity3D人脸检测应用程序。该应用程序应该每秒检测10张脸。但是,每次人脸检测大约需要50毫秒,因此我决定让人脸检测在另一个线程的后台运行,以防止出现小的延迟峰值(应用程序需要每帧更新一次视觉内容,50毫秒的停止会使其延迟) 问题是线程导致应用程序在iOS上滞后。不穿线时,它用于每秒检测10个面,现在穿线时检测2个面。。它在Android上运行良好 奇怪的是,该应用程序在iOS上的前5秒运行良好。不管它是否检测到人脸,5秒后会出现严重的延迟。编辑:如果我暂停
IEnumerator FaceDetection()
{
while (true)
{
if (faceDetectionThreadDone)
{
rgbaMat = webCamTextureToMatHelper.GetMat();
if (rgbaMat != null)
{
OpenCVForUnityUtils.SetImage(faceLandmarkDetector, rgbaMat);
faceDetectionThreadDone = false;
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
// heavy computing stuff (50 ms)
List<UnityEngine.Rect> detectResult = faceLandmarkDetector.Detect();
if (detectResult.Count > 0)
{
points = faceLandmarkDetector.DetectLandmark(detectResult[0]);
}
faceDetectionThreadDone = true;
}).Start();
}
}
yield return new WaitForSeconds(0.1f);
}
}
IEnumerator人脸检测()
{
while(true)
{
如果(faceDetectionThreadDone)
{
rgbaMat=webCamTextureToMatHelper.GetMat();
if(rgbaMat!=null)
{
OpenCVForUnityUtils.SetImage(faceLandmarkDetector,rgbaMat);
faceDetectionThreadDone=false;
新线程(()=>
{
Thread.CurrentThread.IsBackground=true;
//重型计算设备(50毫秒)
List detectResult=faceLandmarkDetector.Detect();
如果(detectResult.Count>0)
{
points=faceLandmarkDetector.DetectLandmark(detectResult[0]);
}
faceDetectionThreadDone=true;
}).Start();
}
}
收益率返回新WaitForSeconds(0.1f);
}
}
我如何创建新线程是否存在严重问题?我在某个地方读到过,一旦执行完毕,它们就会被垃圾收集器清理掉。这可能会导致延迟吗?构建设置设置为高性能等
编辑:好的,我现在非常确定这个问题与内存管理无关。我在Xcode中运行了内部分析器,并观察了堆的使用量。当垃圾收集器启动时,性能没有受到影响
我测试应用程序的设备:iPhone 6、索尼Z3、三星S4创建和启动
线程非常昂贵。每次
Thread(() =>
{
//Code
}).Start();
调用时,将分配大约1MB的内存。添加在其中发生的其他内存分配,例如列表
(detectResult)创建
同时,产生返回新的WaitForSeconds(0.1f)代码>分配内存,但我认为这不是问题所在。您可以通过在while循环之前声明WaitForSeconds
,然后使用它来防止这种情况
比如说,
//Create instance of WaitForSeconds once, before the while loop
WaitForSeconds waitForSeconds = new WaitForSeconds(0.1f);
while (true){
//your Thread code
}
yield return waitForSeconds; //No more memory allocation
不要真的认为这是主要问题,但我把它告诉你,你可以做到这一点。对于我上面提到的线程
问题,您应该创建一个while
循环,该循环处理数据,然后在主线程
中执行输出。基本上是一个线程函数,它将永远循环,而不是每次都创建一个新的线程
有一个名为的插件,允许您从另一个线程调用Unity API函数。你可能想用它。它有付费和免费版本。免费版本中不包含示例。这是唯一的区别,但是你可以在我发布的链接上下载它和它的例子
下面是如何使用该API的一般示例。阅读代码中的注释。你的工作是把问题中的代码放在适当的位置,这很容易做到
bool keepProcessing;
UnityThreading.ActionThread myThread;
void Start()
{
keepProcessing = true;
//Create Thread once
myThread = UnityThreadHelper.CreateThread(() =>
{
//Will process Data forever!
while (keepProcessing)
{
//Do heavy computing stuff
//Computing Done! Do something with the output data
UnityThreadHelper.Dispatcher.Dispatch(() =>
{
//You can safely call Unity API functions inside this codeblock
}
//Wait so that Unity won't Freeze
Thread.Sleep(1);
}
});
}
void stopProcessing()
{
keepProcessing = false;
myThread.Abort();
}
最后,我建议您重新设计DetectLandmark
函数,将array
作为参数,而不是List
。分配足够的阵列内存一次,然后重新使用。这将完全删除应用程序中的内存分配。创建和启动线程
非常昂贵。每次
Thread(() =>
{
//Code
}).Start();
调用时,将分配大约1MB的内存。添加在其中发生的其他内存分配,例如列表
(detectResult)创建
同时,产生返回新的WaitForSeconds(0.1f)代码>分配内存,但我认为这不是问题所在。您可以通过在while循环之前声明WaitForSeconds
,然后使用它来防止这种情况
比如说,
//Create instance of WaitForSeconds once, before the while loop
WaitForSeconds waitForSeconds = new WaitForSeconds(0.1f);
while (true){
//your Thread code
}
yield return waitForSeconds; //No more memory allocation
不要真的认为这是主要问题,但我把它告诉你,你可以做到这一点。对于我上面提到的线程
问题,您应该创建一个while
循环,该循环处理数据,然后在主线程
中执行输出。基本上是一个线程函数,它将永远循环,而不是每次都创建一个新的线程
有一个名为的插件,允许您从另一个线程调用Unity API函数。你可能想用它。它有付费和免费版本。免费版本中不包含示例。这是唯一的区别,但是你可以在我发布的链接上下载它和它的例子
下面是如何使用该API的一般示例。阅读代码中的注释。你的工作是把问题中的代码放在适当的位置,这很容易做到
bool keepProcessing;
UnityThreading.ActionThread myThread;
void Start()
{
keepProcessing = true;
//Create Thread once
myThread = UnityThreadHelper.CreateThread(() =>
{
//Will process Data forever!
while (keepProcessing)
{
//Do heavy computing stuff
//Computing Done! Do something with the output data
UnityThreadHelper.Dispatcher.Dispatch(() =>
{
//You can safely call Unity API functions inside this codeblock
}
//Wait so that Unity won't Freeze
Thread.Sleep(1);
}
});
}
void stopProcessing()
{
keepProcessing = false;
myThread.Abort();
}
最后,我建议您重新设计DetectLandmark
函数,将array
作为参数,而不是List
。分配足够的阵列内存一次,然后重新使用。这将完全删除应用程序中的内存分配。将Application.targetFrameRate设置为1/30帧中的15,29/30帧中的60解决了此问题。。。。。。