【问题标题】:Error: The calling thread cannot access this object because a different thread owns it - Kinect错误:调用线程无法访问此对象,因为不同的线程拥有它 - Kinect
【发布时间】:2013-09-18 22:22:23
【问题描述】:

所以我正在尝试使用 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 编程的新手。我只有一个线程,所以我不知道为什么会出现异常。有什么帮助吗?

【问题讨论】:

  • 您有 2 个线程。运行应用程序的主线程和您创建的用于运行 videoDisplay 的线程。 kinectVideo 对象从何而来?
  • 我明白了。因此,如果我理解正确,当我为 videoDisplay 创建线程时,我创建的线程 (updateVideoThread) 和程序的主线程都尝试运行该方法,因此会调用异常? kinect 对象来自这行代码---->using Microsoft.Kinect; With is more up and dint 复制到这里。
  • 不是他们都在尝试运行该方法,可能是kinectVideo对象属于主线程。 kinectVideo 是什么类的实例,它是在哪里创建的?它的命名方式看起来像是一个变量,我在 Microsft.Kinect 中看不到任何名为 kinectVideo 的静态类。它是表单上的对象还是什么?
  • 我先说这是一个 WPF 项目。其次,这是表单上的一个对象。更具体地说,这是创建对象的 XAML 中的锥体--> ""

标签: multithreading exception sdk kinect


【解决方案1】:

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

看看这个帖子上的答案,它看起来和你遇到的问题完全相同
The calling thread cannot access this object because a different thread owns it.How do i edit the image?

根据这些答案,您应该将 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() 对您来说可能是一个更好的选择,但它可能会影响内存。

【讨论】:

    【解决方案2】:

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

    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(() => { ... }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      相关资源
      最近更新 更多