使用Windows Presentation Foundation的Windows Workflow Foundation

时间:2010-07-01 06:40:06

标签: .net wpf workflow-foundation

Iam尝试在Workflow Com服务中创建WPF窗口 但我得到以下错误:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
   at System.Windows.Input.InputManager..ctor()
   at System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
   at System.Windows.Input.InputManager.get_Current()
   at System.Windows.Input.KeyboardNavigation..ctor()
   at System.Windows.FrameworkElement.FrameworkServices..ctor()
   at System.Windows.FrameworkElement.EnsureFrameworkServices()
   at System.Windows.FrameworkElement..ctor()
   at System.Windows.Controls.Control..ctor()
   at System.Windows.Window..ctor()
   at PACIExpress.SelectLanguage..ctor()

有人能帮帮我吗?

2 个答案:

答案 0 :(得分:2)

Exception确切地说明了问题:

  

System.InvalidOperationException:调用线程必须是STA,因为许多UI组件都需要这个。

首先,如果'Workflow Com Service'类似于WCF或Web服务,那么它不是可以拥有用户界面的桌面应用程序。

您的应用必须是STA。

MTA和STA之间的区别:

  

Could you explain STA and MTA?

有关WPF和STA的信息: http://msdn.microsoft.com/en-gb/magazine/cc163328.aspx

如果你有一个入口点方法,你想使用STAThread属性,请参阅此处获取更多信息:

  

http://blogs.msdn.com/b/jfoscoding/archive/2005/04/07/406341.aspx   http://msdn.microsoft.com/en-us/library/system.stathreadattribute.aspx

希望有所帮助!

答案 1 :(得分:2)

Kieren的回答解释了问题的本质,即Workflow Foundation线程是MTA线程,而WPF需要STA线程。 Kieren的回答并未解释如何解决问题。

每当我需要从MTA线程访问WPF内容时,我都会创建一个用于访问内容的STA线程。我已经使用了两个解决方案,这两个解决方案都运行良好:

合并的STA线程

当WPF对象不需要存在于当前方法调用之外时,我使用我编写的STAThreadPool类。 STAThreadPool实现System.Threading.ThreadPool的基本功能,但创建其线程STA而不是MTA。它还有一个RunOnSTAThread方法,该方法对用户工作项进行排队,然后等待该项完成。

专用STA线程

此解决方案具有更多开销,但是在任何时候WPF对象可能存在多个方法调用时都需要。同样有一个“RunOnSTAThread”方法,在这种情况下通过以下方式实现:

  1. 如果当前线程是STA,则执行操作
  2. 查看字典以查看此MTA线程是否存在STA线程(必须锁定字典)。
  3. 如果未找到STA线程:创建STA线程并将其添加到字典中。
  4. 将操作存储在STA线程中,通知STA线程执行,并等待其完成
  5. 每个STA线程运行一个执行此操作的循环:

    1. 如果相应的MTA线程未处于活动状态,请退出
    2. 等待动作准备好运行的信号,超时10秒。如果超时,请转到步骤1
    3. 执行行动
    4. 表示行动已完成
    5. 转到第1步
    6. 这个解决方案实际上比编写良好的STAThreadPool更少的代码,但如果有很多线程可能效率较低。