views:

36

answers:

2

Iam Trying To Create a WPF Window in a Workflow Com Service but iam getting the following Error:

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()

can anybody help me please ?

+2  A: 

The Exception states the problem exactly:

System.InvalidOperationException: The calling thread must be STA, because many UI components require this.

First of all if a 'Workflow Com Service' is anything like a WCF or Web service, it's not a desktop app that can have a user interface.

Either way your app must be STA.

The difference between MTA and STA:

http://stackoverflow.com/questions/127188/could-you-explain-sta-and-mta

Info about WPF and STA: http://msdn.microsoft.com/en-gb/magazine/cc163328.aspx

And if you have an entry point method, you want to use the STAThread attribute, see here for more information:

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

Hope that helps!

Kieren Johnstone
+2  A: 

Kieren's answer explains the essence of the problem, namely that the Workflow Foundation thread is a MTA thread whereas WPF requires STA threads. Kieren's answer does not explain how to fix the problem.

Whenever I need to access WPF content from a MTA thread I create a STA thread with which to access the content. I have used two solutions for this, both of which have worked well:

Pooled STA threads

When WPF objects don't need to exist beyond the current method call, I use a STAThreadPool class I wrote. STAThreadPool implements the basic features of System.Threading.ThreadPool, but creates its threads STA instead of MTA. It also has a RunOnSTAThread method which queues a user work item then waits for that item to complete.

Dedicated STA threads

This solution is has more overhead but is required any time WPF objects may exist for multiple method calls. Again there is a "RunOnSTAThread" method, which in this case is implemented by:

  1. If the current thread is STA, just execute the action
  2. Look in the dictionary to see if there is a STA thread for this MTA thread (must lock dictionary).
  3. If no STA thread was found: Create a STA thread and add it to the dictionary.
  4. Store the action in the STA thread, signal the STA thread to execute, and wait for it to complete

Each STA thread runs a loop that does this:

  1. If corresponding MTA thread is not alive, exit
  2. Wait for signal that Action is ready to run, with 10s timeout. If timeout, go to step 1
  3. Execute Action
  4. Signal that Action is complete
  5. Go to step 1

This solution is actually less code than a well-written STAThreadPool, but may be less efficient if there are many threads.

Ray Burns