WPF调度程序 {"调用线程无法访问此对象,因为不同的线程拥有它。"}

17

首先我需要说我对WPF和C#都是新手。

应用程序:创建Mandelbrot图像(GUI)

在这种情况下,我的调度程序完美地工作:

  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中的图像。

如果我不将计算放在单独的线程中,则无法刷新或构建图像。

5个回答

34

如果你希望在不同的线程之间共享对象,那么请始终在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()));
        }
    }

7

3

当你获取一个Dispatcher时,你会为每个不同的线程获得一个不同的Dispatcher。

this.Dispatcher可能会给你另一个Dispatcher而不是UI线程的Dispatcher,因此你会收到该错误。

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

如果你从另一个线程使用Dispatcher.CurrentDispatcher,同样会出现相同的错误。


2

您也可以使用队列机制在线程之间传递信息。毕竟,这就是Windows架构的工作方式。这就是调度程序所做的事情。您正在将引用传递给委托,但该引用并非由WPF线程拥有。

因此,是的,您有基本的想法,但您需要实际使用 Action<T>(T object) 或在您的情况下:

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

1
不会有任何区别,因为你仍然在共享被引用的对象。 - Ben Voigt

2
你是在工作线程上创建位图(bmp),然后将其传递给UI线程 - 这就是失败的原因。
你需要在UI线程上创建图像。您可能需要某种方式来引用要显示的图像并将该信息传递给UI。

1
你不需要在UI线程上创建图像。但是,当另一个线程正在修改它时,你不能从一个线程中使用它(.NET假定除非你将其标记为冻结,否则它将再次被修改)。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接