I am attempting to write a printed form in F# using WPF controls—-and do so in an asynchronous workflow. Being new to this, I can’t figure out how to place the wpf controls, consumed by the F# asynchronous block, on a STA thread, without blocking the main thread.
I have a lot of printed forms and do not want to block the main thread.
How is a STA thread created for the F# asynchronous workflow?
Thanks in advance for any help.
In pure WPF I don't think you have STA - that concept comes from the COM model. What you do have is a specific UI thread that must be used for communicating with the UI. To get that thread you can use SynchronizationContext.Current property when you are certain you are on the UI thread (e.g. in an event handler). Note: If SynchronizationContext.Current is null then you will be running in the thread pool rather than on the UI thread.
If you then pass that SynchronizationContext object into your async {} code, you should be able to rejoin the UI thread by calling Async.SwitchToContext
Related
Why is it that the thread that created the control is the one that can update it? Why didn't MS give people the ability to use locking and other thread synchronization techniques for reading and writing to properties on UI controls with multiple threads.
The short description per MSDN is
WPF’s threading model was kept in sync with the existing User32
threading model of single threaded execution with thread affinity. The
primary reason for this was interoperability – systems like OLE 2.0,
the clipboard, and Internet Explorer all require single thread
affinity (STA) execution
The longer description is this:
Most objects in WPF derive from DispatcherObject, which provides the
basic constructs for dealing with concurrency and threading. WPF is
based on a messaging system implemented by the dispatcher. This works
much like the familiar Win32 message pump; in fact, the WPF dispatcher
uses User32 messages for performing cross thread calls.
There are really two core concepts to understand when discussing
concurrency in WPF – the dispatcher and thread affinity.
During the design phase of WPF, the goal was to move to a single
thread of execution, but a non-thread "affinitized" model. Thread
affinity happens when a component uses the identity of the executing
thread to store some type of state. The most common form of this is to
use the thread local store (TLS) to store state. Thread affinity
requires that each logical thread of execution be owned by only one
physical thread in the operating system, which can become memory
intensive. In the end, WPF’s threading model was kept in sync with the
existing User32 threading model of single threaded execution with
thread affinity. The primary reason for this was interoperability –
systems like OLE 2.0, the clipboard, and Internet Explorer all require
single thread affinity (STA) execution.
Given that you have objects with STA threading, you need a way to
communicate between threads, and validate that you are on the correct
thread. Herein lies the role of the dispatcher. The dispatcher is a
basic message dispatching system, with multiple prioritized queues.
Examples of messages include raw input notifications (mouse moved),
framework functions (layout), or user commands (execute this method).
By deriving from DispatcherObject, you create a CLR object that has
STA behavior, and will be given a pointer to a dispatcher at creation
time.
You can read the full article here
Personally I prefer WPF's single-threaded model over having to use locking and thread synchronization techniques. The Dispatcher can be used to pass messages to the main UI thread at different priority levels, which takes care of the majority of small background processes, and if you need any heavy processing then you can still create your own background thread for that.
WPF, like virtaully all UI toolkits, works by pumping a message loop. Since messages can come at any time and affect any control you would need a global lock. And to make it less error prone you probably want a function that would invoke a delegate under the lock. Perhaps something like this:
Dispatcher.Invoke(Delegate, Object())
The fact that this gets marshalled to the UI thread instead of acquiring a global lock is just an implementation detail.
I need some help understanding the difference between STA and MTA with respect to the winform and console application. I am using a third party COM interface to execute functions in parallel, using parallel.invoke. When i do this in console application everything works fine and code actually runs in parallel. But when i do the same thing in Winform it's sequential, and if i remove the STAtrhread tag above the entry point of winform , it start to work fine in parallel. Can anyone explain this behavior?,Any suggestions would be nice!
COM has a feature that's entirely missing in .NET. A COM class can specify whether it is thread-safe or not. It does so with a key in the registry named ThreadingModel. Just like most .NET classes, the vast majority of COM classes are not thread-safe so they specify "Apartment". Which is a somewhat obscure term that implies "only call me from the thread on which I was created". Which automatically provides thread-safety.
To make that work, a thread that creates COM objects has to indicate what kind of support it is willing to provide for COM classes that are not thread safe. An STA thread is a safe home. Requirement is that the thread pumps a message loop, like any UI thread does. The message loop is the mechanism by which COM marshals a call from a worker thread to the thread that created the object. A thread that joins the MTA specifically says it does not provide support.
COM has to do something about MTA threads, they are not suitable for COM objects that are not thread safe. It creates a new thread, an STA thread to give the COM object a safe home. That's quite inefficient, every method call has to be marshaled. And risky, a COM class may still be thread-unsafe if its objects share state internally.
So what's happening in your Winforms case is that you created all the objects on the main thread, which is an STA. And make calls from parallel worker threads, those calls all get marshaled and serialized back to the STA thread. Inevitably, they execute one-by-one and you get no concurrency.
In your Console case, you created them on an MTA thread. So COM is forced to create threads for each object. The method calls on your worker threads are still marshaled, but now to multiple threads. So now you do get concurrency, at the cost of significant overhead, a bunch of extra threads. And the risk of failure when the server shares state internally.
Make the Winforms case the same as the Console case by creating the COM objects on a worker thread. Do test it very thoroughly.
STA and MTA are both "threading models" for COM/ActiveX, dating back to the mid 1990's.
Here's a good link:
http://msdn.microsoft.com/en-us/library/ms809971.aspx
STA:
A process has one single-threaded apartment (STA) for each thread that
called CoInitialize. Each of these apartments, in turn, may have zero
or more COM objects associated with them. As the name implies,
however, only one specific thread (the thread that created the
apartment by calling CoInitialize) may directly access the objects
within the apartment
MTA:
Although multi-threaded apartments, sometimes called free-threaded
apartments, are a much simpler model, they are more difficult to
develop for because the developer must implement the thread
synchronization for the objects, a decidedly nontrivial task. On the
positive side, removing an STA's synchronization mechanism gives the
developer much finer control over the use of thread synchronization.
They can apply it where it is actually needed rather than taking the
very conservative approach of STAs, which synchronize access to the
entire apartment.
One issue is choosing the best threading model for your component (the default is STA, IIRC). Another issue is what the runtime will do if you need to marshal data between your component and a component that uses a different threading model. The link above discusses both.
I have a very complex WPF application where the pages that I display and processed are in dlls. This works fine so far.
I set up a timer in the main page of the app that looks for communication coming in from an external source. When I get a communication (and I am being vague to not not add confusion) I parse it and if the message is "xyx" I need to start the XYL dll's UI. I get the calling thread must be sta bacause many ui components require this.
I see the write ups on the web about having to call the Invoke() and that I can't use a worker thread but rather a background thread.
Is my problem the System.Timers.Timer that I am using? Is that causing a worker thread? I am not sure where in my calls I need to start a thread to run this (or how to handle it).
Any suggestions?
System.Timers.Timer runs on a worker thread and cannot access UI elements. See here and here for more information on that.
It's ok to use that kind of timer, you just need to get back to the UI (dispatcher) thread before you touch the UI pieces. You can do this by calling Dispatcher.Invoke or Dispatcher.BeginInvoke and passing in the delegate you want to run. That'll get the new UI pieces onto your original UI thread. If you want them to run on their own UI thread (perhaps in a different window) then you need to set that up yourself.
Timers normally run on a threadpool thread which are MTA.
Use a DispatcherTimer instead or use Dispatcher.Invoke. The dll's UI will then run on the same thread as main page's UI (which is STA)
If you want the dll's UI to run on a different thread you need to create the thread yourself and set it to STA.
How does the Dispatcher thread work in wpf a UI control?
Edit.
If you have a long running task, delegate it to a background thread using a BackGroundWorker, and then you won't need to use the dispatcher to pass messages back to the UI. This is a very good article.
Its a very broad question. I suggest you start here with WPF Architecture.
Most objects in WPF derive from
DispatcherObject, which provides the
basic constructs for dealing with
concurrency and threading. WPF is
based on a messaging system
implemented by the dispatcher. This
works much like the familiar Win32
message pump; in fact, the WPF
dispatcher uses User32 messages for
performing cross thread calls.
There are really two core concepts to
understand when discussing concurrency
in WPF – the dispatcher and thread
affinity.
During the design phase of WPF, the
goal was to move to a single thread of
execution, but a non-thread
"affinitized" model. Thread affinity
happens when a component uses the
identity of the executing thread to
store some type of state. The most
common form of this is to use the
thread local store (TLS) to store
state. Thread affinity requires that
each logical thread of execution be
owned by only one physical thread in
the operating system, which can become
memory intensive. In the end, WPF’s
threading model was kept in sync with
the existing User32 threading model of
single threaded execution with thread
affinity. The primary reason for this
was interoperability – systems like
OLE 2.0, the clipboard, and Internet
Explorer all require single thread
affinity (STA) execution.
Given that you have objects with STA
threading, you need a way to
communicate between threads, and
validate that you are on the correct
thread. Herein lies the role of the
dispatcher. The dispatcher is a basic
message dispatching system, with
multiple prioritized queues. Examples
of messages include raw input
notifications (mouse moved), framework
functions (layout), or user commands
(execute this method). By deriving
from DispatcherObject, you create a
CLR object that has STA behavior, and
will be given a pointer to a
dispatcher at creation time.
Is there a usable equivalent of AppDomain.UnhandledException for Silverlight? I say usable, because, although the method exists in Silverlight, MSDN has it marked as [SecurityCritical].
What I'd like is to receive notification of Exceptions happening on background or ThreadPool threads so that I can log them. Application.UnhandledException was another candidate, but it looks like that only recieves exceptions from the UI thread.
Are you using Silverlight 3? I just put together a simple SL3 application that showed that Application.UnhandledException was notified on unhandled exceptions from the UI thread, a thread pool thread, a worker thread and a background worker thread.
You may have convinced yourself prematurely. :)