错误:调用线程无法访问此对象,因为其他线程拥有它-Kinect



所以我正在尝试用SDK编程一个kinect传感器。这是代码。

public partial class MainWindow : Window
{
    bool mirror=false;
    bool displayActive = true;
    int redOffset;
    int greenOffset;
    int blueOffset;
    WriteableBitmap colorImageBitmap = null;
    KinectSensor myKinect;
    public MainWindow()
    {
        InitializeComponent();
    }
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        kinectVideo.Source = colorImageBitmap;
        myKinect = KinectSensor.KinectSensors[0];
        if (KinectSensor.KinectSensors.Count == 0)
        {
            MessageBox.Show("No Kinects detected", "Camera Viewer");
            Application.Current.Shutdown();
        }
        myKinect.ColorStream.Enable();
        myKinect.Start();
        Thread updateVideoThread;
        updateVideoThread = new Thread(new ThreadStart(videoDisplay));
        updateVideoThread.Start();
    }

    void videoDisplay()
    {
        while (displayActive)
        {
            using (ColorImageFrame colorFrame = myKinect.ColorStream.OpenNextFrame(10))
            {
                if (colorFrame == null) continue;
                byte[] colorData = new byte[colorFrame.PixelDataLength];
                colorFrame.CopyPixelDataTo(colorData);

                //----------------------------Methodos 2 for image color adjustment------------------------------------------------------------------------------------
                updateColor(colorData);
                //----------------------------Methodos 1 for mirror------------------------------------------------------------------------------------
                if (mirror) { reflectImage(colorData, colorFrame.Width, colorFrame.Height); }
                //----------------------------Methodos 2 for update image------------------------------------------------------------------------------------
                kinectVideo.Source = colorImageBitmap;
                if (colorImageBitmap == null)
                {
                    this.colorImageBitmap = new WriteableBitmap(colorFrame.Width,
                                                                    colorFrame.Height,
                                                                    96, // DpiX
                                                                    96, // DpiY
                                                                    PixelFormats.Bgr32,
                                                                    null);
                }
                this.colorImageBitmap.WritePixels(new Int32Rect(0, 0, colorFrame.Width, colorFrame.Height),
                                                                colorData, // video data
                                                                colorFrame.Width * colorFrame.BytesPerPixel, // stride,
                                                                 0 // offset into the array - start at 0
                                                                 );
            }
        }
    }

在"kinectVideo.Source=colorImageBitmap;"一行中,is给了我一个异常,说"调用线程无法访问此对象,因为另一个线程拥有它。"我不明白为什么。我是C#和Visual Studio编程的新手。我只有一个线程,所以我不知道为什么会出现异常。有什么帮助吗?

好的,所以基本上你试图从一个不是主线程的线程更新UI,如果没有一些描述的调用,这永远不会起作用。

看看这个帖子上的答案,它看起来和你遇到的问题完全一样
调用线程无法访问此对象,因为其他线程拥有它。如何编辑图像?

根据这些答案,您应该将videoDisplay()中的代码更改为如下所示:

...    
Action action = delegate { kinectVideo.Source = colorImageBitmap; };
kinectVideo.Dispatcher.Invoke(action);
if (colorImageBitmap == null){
...

如果这不起作用,请尝试:

...    
colorImageBitmap.Freeze();
Action action = delegate { kinectVideo.Source = colorImageBitmap; };
kinectVideo.Dispatcher.Invoke(action);
if (colorImageBitmap == null){
...

并且考虑到您也使用kinectVideo.Source=colorImageBitmap;在Window_Loaded方法中,您可能也需要在那里使用.Freeze()。

我对XAML和Freeze()不是很熟悉,但由于colorImageBitmap似乎没有在这两个方法中初始化,这可能会给您带来其他问题
使用GetAsFrozen()可能是一个更好的选择,但它可能会影响内存。

我找到问题的答案了吗。这就是我所做的。

1) 声明了线程

Private Backgroundworker _worker;

2) 创建一个实例,订阅DoWork事件,并启动新线程

this._worker=new BackgroundWorker();
this._worker.DoWork += Worker_DoWork;
this._worker.RunWorkerAsync();

3) 编写事件处理程序

private void Worker_DoWork(object sender, DoWorkEventArgsn e) { ... }

4) 把这些代码放在创建位图的地方和重写位图的地方。

this.ColorImageElement.Dispatcher.BeginInvoke(new Action(() => { ... }

相关内容

最新更新