我正在编写一个应用程序,该应用程序应显示最多4个Kinect的跟踪骨架。当用户按下Start
按钮时,应该开始跟踪然后在表单上绘图。来自Java背景我对在C#中使用delegates
和EventHandlers
知之甚少。到目前为止,我的代码看起来像这样,但它完全冻结了表单。如何解决?
private void MainWindow_Load(object sender, EventArgs e)
{
ProgramLoop();
}
private void ProgramLoop()
{
int sensorCount = 0;
foreach (KinectSensor connectedSensor in KinectSensor.KinectSensors)
{
if (connectedSensor.Status == KinectStatus.Connected)
{
connectedSensor.SkeletonStream.Enable();
connectedSensorsArray.Add(connectedSensor);
connectedSensor.Start();
sensorCount++;
}
}
}
private void start_Click(object sender, EventArgs e)
{
trackSkeletons();
}
private void trackSkeletons()
{
while (true)
{
foreach (KinectSensor sensor in connectedSensorsArray)
{
SkeletonFrame skeletonFrame = sensor.SkeletonStream.OpenNextFrame(200);
if (skeletonFrame != null)
{
if (initSkeletons == null)
{
initSkeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
}
skeletonFrame.CopySkeletonDataTo(initSkeletons);
skeletonFrame.Dispose();
Skeleton initSkeleton = initSkeletons.Where(s => s.TrackingState == SkeletonTrackingState.Tracked).FirstOrDefault();
if (initSkeleton != null)
{
switch (connectedSensorsArray.IndexOf(sensor))
{
case 0:
mainQueue.Enqueue(initSkeleton);
break;
case 1:
secondQueue.Enqueue(initSkeleton);
break;
case 2:
thirdQueue.Enqueue(initSkeleton);
break;
case 3:
fourthQueue.Enqueue(initSkeleton);
break;
}
}
}
}
//dequeue Skeletons and draw them
}
}
答案 0 :(得分:1)
你应该使用计时器而不是while(true)
。
您的计时器将每隔X秒执行一次,当他被召唤时,您可以调用自己的函数trackSkeletons()
。
答案 1 :(得分:0)
正如我所说你需要使用线程,我不知道kinect sdk是如何工作的,但只要trackSkeletons()不会写入另一个线程正在使用的数据,它就应该很好,否则你需要解决这个问题某种同步。但我认为它应该像这样工作
private void start_Click(object sender, EventArgs e)
{
Thread thread = new Thread(trackSkeletons);
thread.Start();
}
在trackSkeletons中你可以在一段时间内(但仍在其中)添加一段时间的睡眠
while(true)
{
//code
Thread.Sleep(50);
}
答案 2 :(得分:0)
首先,我认为您需要休息条件来停止跟踪。
如果您不想冻结UI,也需要使用线程。
对于线程来说非常简单:
Thread t = new Thread(trackSkeletons);
t.Start();
现在在您的课程中,您应该添加一个私有布尔字段_trackSkeletons
,以便您的点击事件如下所示:
Thread t = new Thread(trackSkeletons);
_trackSkeletons = true;
t.Start();
在trackSkeletons方法中,使用:
while(_trackSkeletons)
{
....
}
这使您可以在需要时停止线程(可能通过单击“停止”按钮)。
Vajura建议的Thread.Sleep
方法也很有用。
在Winform应用程序中使用线程时要知道的最后一件事是:您不能直接从线程更改任何用户界面元素,否则您将获得异常。您需要使用Invoke
方法来执行此操作。
答案 3 :(得分:0)
使用像这样的需要线程;
private void start_Click(object sender, EventArgs e)
{
Thread t = new Thread(trackSkeletons);
t.Start();
}
帮助:Threads