WPF Dispatcher {“调用线程不能访问这个对象,因为一个不同的线程拥有它。”}

问题描述:

首先,我需要说我很喜欢WPF和C#。 应用程序:创建曼德尔布罗图片(GUI) 我分派工作完全此这种情况下:WPF Dispatcher {“调用线程不能访问这个对象,因为一个不同的线程拥有它。”}

private void progressBarRefresh(){ 

     while ((con.Progress) < 99) 
     { 
      progressBar1.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate 
       { 
        progressBar1.Value = con.Progress; 
       } 
      )); 
     } 
    } 

我得到的消息(标题)特林当与下面的代码来做到这一点:

bmp = BitmapSource.Create(width, height, 96, 96, pf, null, rawImage, stride); 

this.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate 
      {      
       img.Source = bmp; 
       ViewBox.Child = img; //vllt am schluss 
      } 
     )); 

我将尝试解释我的程序如何工作。 我创建了一个新的线程(因为GUI不响应)来计算像素和颜色。在这个线程(方法)中,在计算准备就绪后,我使用Dispatcher刷新ViewBox中的图像。

当我不把计算放在单独的线程中时,我可以刷新或构建我的图像。

您正在您的worker(?)线程上创建位图(bmp),然后将它传递给UI线程 - 这是失败的。

您需要在UI线程上创建图像。您可能需要某种方法来引用您想要显示的图像,并将信息传递给UI。

+1

您不需要在UI线程上创建图像。你不能从一个线程在另一个线程上使用它(而.NET假定除非你将它标记为* freeze *,否则它将被再次修改)。 – 2010-06-06 02:18:33

MSDN说:“冻结的Freezable可以跨线程共享。”

也许这线程将帮助:http://social.msdn.microsoft.com/Forums/en-US/windowswic/thread/9223743a-e9ae-4301-b8a4-96dc2335b686

你也可以使用一个排队机制在线程之间传递消息。毕竟,这就是Windows架构的工作原理。这就是调度员正在做的事情。您正将一个引用传递给该委托,该委托不属于WPF线程。

所以,是的,你有基本的想法,但实际上你需要使用Action<T>(T object)传位给其他线程,或在您的情况:

Dispatcher.Invoke(DispatcherPriority.Send, new Action<Bitmap>(delegate(Bitmap img) { 
    do things here... 
}), bmp); 
+1

不会有所作为,您仍然共享被引用的对象。 – 2010-06-06 02:19:19

万一你希望对象是在不同线程之间共享,然后总是在UI线程上创建该对象。稍后,当您想要访问该对象时,可以检查是否有权访问该对象。如果您没有访问权限,请通过UI线程访问重新调用该函数。下面的示例代码:

private void YourMethod() 
    { 
     if (Application.Current.Dispatcher.CheckAccess()) 
     { 
      // do whatever you want to do with shared object. 
     } 
     else 
     { 
      //Other wise re-invoke the method with UI thread access 
      Application.Current.Dispatcher.Invoke(new System.Action(() => YourMethod())); 
     } 
    } 

当你得到一个Dispatcher你会得到一个不同的每一个不同的线程。

this.Dispatcher可能会给你另一个Dispatcher而不是UI,所以你会得到那个错误。

尝试使用Application.Current.Dispatcher代替,这将始终返回UI线程的分派器。

如果您从其他线程使用Dispatcher.CurrentDispatcher,则可能会发生同样的错误。