代码之家  ›  专栏  ›  技术社区  ›  Scott Whitlock

创建System.Windows.Controls.Image会引发异常-如何使用Dispatcher来实例化它?

  •  4
  • Scott Whitlock  · 技术社区  · 14 年前

    我正在一段代码上运行我的单元测试,该代码在测试中执行以下操作:

    Assert.IsNotNull(target.Icon);
    

    在icon属性的getter中,我执行以下操作:

    System.Windows.Controls.Image img = new System.Windows.Controls.Image();
    

    这将引发此异常:System.InvalidOperationException:调用线程必须是STA,因为许多UI组件都需要这样做。

    我明白这意味着什么,我明白我需要使用调度员,但我对如何使用或为什么使用调度员有点困惑…这是我的ViewModel的一个属性,在运行应用程序时,我不会得到任何这些异常。

    其他信息:这只在我升级到.NET 4时才开始失败。

    4 回复  |  直到 14 年前
        1
  •  1
  •   JaredPar    14 年前

    这里的问题是,您正在单元测试WPF,它需要一个STA才能正常运行,但是单元测试框架正在使用MTA。您需要设置单元测试框架以在STA中运行测试。

    每个框架都有不同的方法。通常只需在Google中输入测试框架名称和STA就可以找到它。

        2
  •  1
  •   Nir    14 年前

    运行单元测试的线程不是STA线程,您可以创建这样的STA线程:

    Thread backgroundThread;
    backgroundThread = new Thread(DoWork);
    backgroundThread.SetApartmentState(ApartmentState.STA);
    backgroundThread.Start();
    

    我不知道您使用的是什么单元测试框架,以及如何更改它的线程模型,但是您需要在线程之前以某种方式调用thread.setapartmentstate。从这里开始。

    “单元状态”是一个COM事物,它是WPF所必需的,因为(正如错误所说)许多WPF控件都需要COM,一个STA线程不会自动有一个与其关联的调度程序。

    通常您不需要担心调度器,如果需要,系统将创建一个调度器。

    如果您确实需要为线程创建一个调度程序,您可以直接读取 Dispacher.CurrentDispacher -但是,除非让分派器控制线程(通过调用dispacher.run),否则无法对该分派器执行任何有意义的操作。

        3
  •  0
  •   Amsakanna    14 年前

    您是否使用其他非UI线程?如果是,您确定他们不访问此属性吗?检查您是否在使用线程或异步运行(如filesystemwatcher)的框架中使用了可能使用此属性的任何组件。不过,更多的代码会有所帮助。

        4
  •  0
  •   Mike Goatly    14 年前

    我认为你可能需要稍微改变一下你的方法。我认为您需要做的是修改视图模型,以便公开图像的URI,而不是图像控件。

    在单元测试中,您将能够验证是否将图像源设置到正确的位置,并且在您的UI中,您只需要将图像控件的源数据绑定到URI。