Kinect框架到达异步

我正在寻找Kinect v2 SDK中的MultiSourceFrameArrived事件的一些帮助。

以下是有问题的方法:

private async void _reader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e) { MultiSourceFrame multiSourceFrame = e.FrameReference.AcquireFrame(); using (var colorFrame = multiSourceFrame.ColorFrameReference.AcquireFrame()) { if (colorFrame != null) { _writeableBitmap.Lock(); colorFrame.CopyConvertedFrameDataToIntPtr( _writeableBitmap.BackBuffer, (uint)(_colorFrameDescription.Width * _colorFrameDescription.Height * _colorFrameDescription.BytesPerPixel), ColorImageFormat.Bgra); _writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, _writeableBitmap.PixelWidth, _writeableBitmap.PixelHeight)); _writeableBitmap.Unlock(); reflectionOverlayControl.ReflectionImageSource = _writeableBitmap; } } using (var bodyFrame = multiSourceFrame.BodyFrameReference.AcquireFrame()) { if (bodyFrame != null) { Body body = JointHelpers.FindClosestBody(bodyFrame); if (body != null) { if (body.IsTracked) { Dictionary bodyComponentDictionary = BuildBodyComponentDictionary(body); foreach (BodyComponent bodyComponent in bodyComponentDictionary.Values.OrderBy(x => x.BodyComponentType)) { bodyComponent.Generate(_writeableBitmap, _coordinateMapper, FrameType.Color, 25); if (!_isRunningFiltering) { _isRunningFiltering = true; try { await Task.Run(() => { bodyComponent.RunFunFiltering(); }); } finally { _isRunningFiltering = false; } } } reflectionOverlayControl.UpdateValues( bodyComponentDictionary, GetFullBodyComponent(body)); } } } } } 

现在,请允许我解释一下:

  • 当一个特定类型的帧从Kinect到达时,该方法运行,这是获取的,我可以在使用块中从中提取ColorFrame和BodyFrame。
  • 第一个“using”块将ColorFrame转换为WPF WriteableBitmap(在构造函数中声明),并将用户控件的ReflectionImageSource设置为等于此WriteableBitmap。 如果这是唯一的使用块,我会在屏幕上看到非常平滑的馈送!
  • 第二个BodyFrame使用确定最接近的主体,如果它被跟踪,然后创建一个填充有人BodyComponents(手,脚,头等)的字典
  • 这里的foreach循环在每个BodyComponent上运行“Generate”函数,该函数设置了它的一些属性。 例如,它设置EncompassingRectangle属性,该属性是旨在包含该组件的Int32Rect对象。

接下来是我需要帮助的地方!

RunFunFiltering方法是一种密集型处理方法,在运行时会创建一个冻结我的UI的阻塞语句。 这会使我的彩色框架video输入非常跳跃! 这个RunFunFiltering方法需要设置BodyComponent类的一些属性,例如矩形应该显示的颜色,它的ReflectionImageSource中的白色像素数,以及使用第一个ReflectionImageSource的一部分设置另一个可写位图。长方形。

由于此对象现在已完成,并且已设置所有属性(并且已对字典中的每个BodyComponent执行此操作),因此我在视图上运行UpdateValues方法,该方法在屏幕上显示BodyComponent类中的有趣内容。

根据@sstan在这篇文章中的一些建议: Async等待保持事件发生

我扔了一个Task.Run()块。 然而,这似乎并没有释放我的UI,我仍然看到一个跳跃的图像。 奇怪的是在那个计时器例子中,它完美地工作! 我在这里有点不知所措。

我是异步function的初学者,但我真的很想了解你的解决方案。 如果您能对代码提供解释,我将非常感激!

更新

我已经能够识别出获取帧的using语句在将UI放置在Task.Run调用之外时阻止了UI。

我不能只使用块异步运行整个BodyFrame,因为我需要第一个“生成”函数始终发生而不是重处理线程的一部分。 两个使用积木似乎不优雅,而是在地毯下推动我的问题……

根据您的评论我理解以下内容:

  • 你有一个异步函数,当一个帧到达时调用
  • 如果没有运行RunFunFiltering任务,则启动一个
  • 如果此任务正在运行,请不要启动新任务
  • 如果RunFunFiltering结束处理结果

 Task taskFunFiltering = null; private async Task ProcessFrame(...) { // a new frame is arrived DoSomeProcessing(...); // only start a new run fun filtering if previous one is finished if (taskFunFiltering == null || taskFunFiltering.IsCompleted) { // start a new fun filtering // don't wait for the result taskFunFiltering = Task.Run( () => ...); } } private async Task RunFunFiltering(...) { // do the filtering and wait until finished var filterResult = await DoFiltering(...); DisplayResult(filterResult); }