Kinect框架到达异步

时间:2015-08-18 13:38:45

标签: c# wpf asynchronous task kinect-sdk

我正在寻找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<BodyComponentType, BodyComponent> 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的阻塞语句。这会使我的彩色帧视频输入非常跳跃!此RunFunFiltering方法需要设置一些BodyComponent类的属性,例如矩形应显示的颜色,其中ReflectionImageSource中的白色像素数,以及使用第一个ReflectionImageSource的一部分设置另一个可写位图。长方形。

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

根据@sstan在这篇文章中的一些建议:Async Await to Keep Event Firing

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

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

更新

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

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

1 个答案:

答案 0 :(得分:0)

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

  • 您有一个在帧到达时调用的异步函数
  • 如果没有运行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);
}