1

在 Silverlight 中,我试图在一系列 3d 四边形上获取网络摄像头(实时)流的帧。我在网络摄像头控制器类的网络摄像头控制器类中使用 VideoSink。然后我在 DrawingSurface 中绘制四边形。但我一直在 CrossAppDomainMarshaledException 中运行。作为一种解决方案,我尝试使用 Dispatcher.BeginInvoke 但有时 BeginInvoke 中的代码似乎跳过或跳出线程。如何处理这样的事情?

    //Video sink capture
    // Is called every time the webcam provides a complete frame (Push)   
    protected override void OnSample(long sampleTime, long frameDuration, byte[] sampleData)
    {
        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            WriteableBitmap bmp = new WriteableBitmap(vidFormat.PixelWidth, vidFormat.PixelHeight);
            RaiseFrameCapture(new FrameCapturedEventArgs { Frame = bmp.FromByteArray(sampleData) });
        });
    }

    //Capture from sink into WebCamController
    void sink_FrameCaptured(object sender, FrameCapturedEventArgs e)
    {

        //List<WriteableBitmap>
        _WebCamSource.AddImage(e.Frame.Clone());

    }


    //XNA draw event handler
    private void DrawingSurface_Draw(object sender, DrawEventArgs e)
    {
        List<WriteableBitmap> frames = new List<WriteableBitmap>();

        if (webCamSource.Frames.Count > 0)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                frames = new List<WriteableBitmap>(webCamSource.Frames.ToArray());

            });
        }

        Draw(frames);

        e.InvalidateSurface();
    }
4

1 回答 1

0

即使您解决了您的问题,我也可以提供一些见解。XNA 与经典的 Silverlight 渲染完全不同。

在经典的 Silverlight 渲染管道中,您以声明方式构建可视化树,并将您的更改推送到它。渲染循环已经看不见了,你很少需要弄乱它。

因此,您希望尽快将更改推送到可视化树。如果您在 UI 线程(正在运行的线程)之外的其他线程中更新可视化树,则更新可能会在渲染期间发生,这将是灾难性的。因此,UI 线程公开了一个消息泵,可通过 Dispatcher.BeginInvoke 使用,以确保线程安全。

使用 XNA,您就没有这些了……因为您实现了自己的渲染管道,并且可以完全控制它。

每次处理网络摄像头帧时,将其设置在网络摄像头控制器中(使用锁)。在每个 XNA 帧中,如果网络摄像头控制器接收到新帧,则获取网络摄像头帧(使用锁)并更新 XNA 纹理(不要为每个帧创建新纹理,这不是有效的)。然后,使用此纹理渲染您的 3D 对象。

于 2011-10-23T20:32:05.853 回答