多线程:ThreadPool和显示图像异常

时间:2014-11-04 13:13:22

标签: c# multithreading exception threadpool kinect

我必须在新线程中显示图像序列,否则kinect会因操作的复杂性而丢失帧。我试过了:

 using (BodyFrame bodyframe = e.FrameReference.AcquireFrame())
            {
                if (bodyframe != null)
                {
                    if (this.bodies == null)
                    {
                        this.bodies = new Body[bodyframe.BodyCount];
                    }
                    //the first time getandrefreshbodydata is called, kinect will allocate each body in the array.
                    //as long as those body objects are not disposed and not set to null in the array,
                    //those body objects will be re-used.
                    bodyframe.GetAndRefreshBodyData(this.bodies);
                    dataReceived = true;
                }
                else Console.WriteLine();
            }
            BodyCustom[] bodiesCustom = deserialize(directoryTxt[frameCount]);

            sw.WriteLine("Frame " + frameCount);
            if (dataReceived)
            {
                sw.WriteLine(dataReceived);
                ThreadPool.QueueUserWorkItem(showImage, frameCount);
..............

并且:

private void showImage(Object frameCount)
    {

       imageReference.Source = new BitmapImage(new Uri(@directoryJpg[(int)frameCount]));
    }

但我有

An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll 
Additional information: Unable to access the object from the calling thread because that object is owned by another thread.

我认为错误取决于对象imageReference,因为我在其他地方使用它,但也通过评论它我得到了这个错误。为什么呢?

我正在使用Image Class(System.Windows.Controls)

1 个答案:

答案 0 :(得分:0)

问题是您无法在后台线程上更新UI。 (如果你把错误信息翻译成英文也有帮助,我会说这里的大多数人都不懂意大利语。)

您需要封送回UI线程以更改图像。

首先,您需要存储当前同步上下文。

这在构造函数中最简单。

public class MyObject 
{
  private SynchronizationContext CurrentSynchronizationContext;

  public MyObject()
  { 
    CurrentSynchronizationContext = System.Threading.SynchronizationContext.Current;
  }
}

接下来,在你的ThreadPool.QueueUserWorkItem操作中(无论是委托还是lambda),添加如下内容:

public void SomeMethodThatDoesSomethingOnABackgroundThread()
{
  ThreadPool.QueueUserWorkItem(() => 
  { 
    // Do some operation that is going to take some time, or can't be done on the UI thread.
    Thread.Sleep(100000); 

    // Operation is complete, let's return the result back to the UI.
    CurrentSynchronizationContext.Post(() => 
    {
      // Change the UI, send a messagebox to the user, change the image. Whatever you need.
      // Also the return isn't necessary, it's just signifying that the method is done. 
      return; 
    },null); 
  }
}