我们在处理多线程的任务的时候,有时候要将任务拆分. 比如我的项目中 . 一方面,要采集每秒300多张图片来供点云生成;同时,要将处理之后的图片分组,进行三维点云的生成;以及对点云的的拼接以及显示;
如何做来满足这些高cpu,gpu的处理呢?多线程,但是,大家一定要注意,在这三个线程中的数据处理,一定要做队列上的缓冲,也就是,自己要设计三个缓冲类,而且是加锁和线程安全的,这样才能同时运作.
而在wpf中,我们很容易使用委托,task等已经分装好的类。下面记录一个这个自己设计的线程类,同时包括开启,停止线程的功能.
//这里就以我 点云拼接并显示异步线程. 案例,来讲解.
//这个类是我设计的保存的3维数据,大家可以依据自己的情况,来写自己的结构
[StructLayout(LayoutKind.Sequential)]
public struct AscDataD3Struct
{
public float u;
public float v;
public float x;
public float y;
public float z;
public byte R;
public byte G;
public byte B;
public float p3x;
public float p3y;
public float p3z;
public int ID;
};
class joinPoint3D
{
public bool IsStop_MatchingD3CloundThread = true;
public CancellationTokenSource CancellAsync_MatchingD3CloundSource =
CancellationTokenSource();
public int MatchingD3Clound_Delay = 10; //设置线程执行时间..
public bool IsClearGetListPoind3s = false;//是否清空当前的点云内存结构.
public List<AscDataD3Struct> GetListAscPointAllD3s = new List<AscDataD3Struct>();//这里储存着最后获取到的点云数量...
public void AscP3dCloundsSplicingMethod()
{
int temp = -1;
try
{
//这里不停的获取其拼接状态 这是我自己写的DLL中的api
temp = yws_InterFaceSDK.DLL_outManegeDataToOsg();
if (temp != 0)
{
Debug.WriteLine("拼接数据失败 :" + temp.ToString());
}
else
{
Debug.WriteLine("拼接数据成功.: " + temp.ToString());
}
}
catch (Exception ex)
{
Debug.WriteLine("点云生成异常: " + ex.Message);
return;
}
finally
{
}
}
//注意这里的 async 以及 await 同时出现。
public async Task AscP3dCloundsSplicingThread(CancellationToken ct)
{
while (IsStop_MatchingD3CloundThread)
{
//判断上面CancellationTokenSource 这个对象是否终止的条件.
if (CancellAsync_MatchingD3CloundSource.IsCancellationRequested)
{
break;
}
//这里就是采用了应答的方式,在其他线程处理好了之后,发一个信号过来,让这个线程处理数据,大家不懂的可以看看多线程 信号这方面的知识
if (IsICPRegister.WaitOne() == true)
{
Task.Factory.StartNew(AscP3dCloundsSplicingMethod).Wait();
}
await Task.Delay(MatchingD3Clound_Delay);
ct.ThrowIfCancellationRequested();
}
}
public async void AscP3dCloundsSplicingTask()
{
IsStop_MatchingD3CloundThread = true;
var aCanccel =
AscP3dCloundsSplicingThread(CancellAsync_MatchingD3CloundSource.Token);
try
{
Debug.WriteLine("点云拼接任务开启....");
await aCanccel;
}
catch
{
if (aCanccel.IsCanceled)
{
Console.WriteLine("点云拼接任务结束....");
}
}
}
public void Async_P3dCloundsSplicingStart()
{
//注意这里,每次开始线程的时候,必须要重新new这个对象,否则上面的线程是开启不了的
CancellAsync_MatchingD3CloundSource = new CancellationTokenSource();
Task.Factory.StartNew(AscP3dCloundsSplicingTask, CancellAsync_MatchingD3CloundSource.Token, TaskCreationOptions.None, TaskScheduler.Default);
}
public void Async_P3dCloundsSplicingStop()
{
try
{
CancellAsync_MatchingD3CloundSource.Cancel();
IsStop_MatchingD3CloundThread = false;
}
catch (Exception ex)
{
Console.WriteLine("点云拼接停止异常: " + ex.Message);
}
}
}
经过以上这么设计,我们的这个线程就可以随时停止,开启,而且不会造成奔溃以及ui上的卡顿,因为它是异步的,健壮性是相当的好,以此这个为模板,写自己的多线程管理类.