By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,203 Members | 1,646 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,203 IT Pros & Developers. It's quick & easy.

STAThread vs non STAThread framework

P: n/a
Hi All,
I have a big problem with STAThread attribute. I'm using XNA framework
connected with WinForms. XNA is working in non STAThread. I have a
problem with displaying CommonDialog forms e.g. OpenFileDialog. I
can't declare a main method as STAThread because of XNA framework. Is
there any way to declare form or some method in form as STAThread (I
think that a method from Form can invoke OpenFileDialog) maybe I'm
wrong.

Do you know how I can resolve a problem?

Thanks.
RK.

Oct 22 '07 #1
Share this Question
Share on Google+
12 Replies


P: n/a
"rafalK" <kr*******@gmail.comwrote in message
news:11*********************@k35g2000prh.googlegro ups.com...
Hi All,
I have a big problem with STAThread attribute. I'm using XNA framework
connected with WinForms. XNA is working in non STAThread. I have a
problem with displaying CommonDialog forms e.g. OpenFileDialog. I
can't declare a main method as STAThread because of XNA framework. Is
there any way to declare form or some method in form as STAThread (I
think that a method from Form can invoke OpenFileDialog) maybe I'm
wrong.

Do you know how I can resolve a problem?

Thanks.
RK.
A Windows Forms application MUST be tagged with the STAThread attribute, no
way around this.
Not sure what you mean with "XNA is working in non STA Thread" though, do
you mean you are running XNA code in a separate thread, or are you running
XNA code on the main thread?
In the latter case, you simply need to add STAThread to your main entry, in
the first case you'll have to delegate the calls to the form by means of
Control.Invoke/BeginInvoke whenever you need to access the From or one of
it's elements.
Willy.

Oct 22 '07 #2

P: n/a
Willy Denoyette [MVP] <wi*************@telenet.bewrote:

<snip>
A Windows Forms application MUST be tagged with the STAThread
attribute, no way around this.
Out of interest, what are the problems one might find without this? For
test purposes I've often created forms which do very little, and rarely
bothered to put the STAThread attribute on them. They've been fine -
but I quite understand that either this was through chance or because I
wasn't using particular components.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Oct 22 '07 #3

P: n/a
The only times I've needed it are when:
* using the Clipboard object
* using ActiveX controls / components

Other than that, I have never seen any issues in the wild when
omitting this...

Marc
Oct 22 '07 #4

P: n/a
I'm running XNA code in main thread and also Form is starting from
main thread. I'm working now without STAThread in main entry and it
works. But as I wrote some is not working. XNA (game library) can't
use STAThread declared in main thread because some components will not
work.
Do You know any way to get round problem ?

Oct 22 '07 #5

P: n/a
Use different threads for any code that /must/ be STA, and code that
/must not/ be STA?

Marc
Oct 22 '07 #6

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Willy Denoyette [MVP] <wi*************@telenet.bewrote:

<snip>
>A Windows Forms application MUST be tagged with the STAThread
attribute, no way around this.

Out of interest, what are the problems one might find without this? For
test purposes I've often created forms which do very little, and rarely
bothered to put the STAThread attribute on them. They've been fine -
but I quite understand that either this was through chance or because I
wasn't using particular components.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Jon,

A couple of the Windows Forms controls are simple wrappers around ActiveX
COM controls, notably all the "Dialog Controls" are AX control wrappers, one
of them being the OpenFileDialog as used by the OP.
Such controls need a *pumping* STA thread to run on.
Now, if you don't initialize your UI thread to enter an STA, the CLR will
initialize the thread to enter the MTA whenever you call into COM for the
first time, that is when you create an instance of say OpenFileDialog. Note
that the v2 SP1 CLR initializes the thread to enter the MTA (if not marked
otherwise) even before it starts the main thread.
FileDialog (the wrapped AX dialog) as all other dialogs, is marked as
requiring an STA, so it can't get instantiated on the calling MTA thread,
COM takes care of this by creating a new thread that gets initialized to
enter an STA and creates the instance of the dialog on this thread and
returns a proxy to the caller.
That mean you'll end with the following (important for this discussion)
threads in a Forms application that doesn't mark it's main UI thread as
STAThread.

Main thread (UI) MTA.
GDI Thread MTA (used by Forms)
STA thread created by COM hosting the FileDialog AX control.

So far so good, the control runs on a compatible thread, and the caller
receives a proxy (a marshaled Interface Pointer). The problem however is
that the STA thread created by COM on your behalf isn't pumping messages,
that means that your OpenFileDialog cannot communicate with the callers
thread. The result is that the dialog cannot be used,it will not even
show-up (I guess) and the UI thread deadlocks.
Note also that the Finalizer (MTA) thread cannot access the controls STA
thread whenever he needs to run the Control's Finalize method. This is no
big deal in this scenario, as the control is non-functional anyway, but it's
a big issue when you have to deal with non-visual AX controls.

Willy.
Oct 22 '07 #7

P: n/a
Willy Denoyette [MVP] <wi*************@telenet.bewrote:
Out of interest, what are the problems one might find without this? For
test purposes I've often created forms which do very little, and rarely
bothered to put the STAThread attribute on them. They've been fine -
but I quite understand that either this was through chance or because I
wasn't using particular components.

A couple of the Windows Forms controls are simple wrappers around ActiveX
COM controls, notably all the "Dialog Controls" are AX control wrappers, one
of them being the OpenFileDialog as used by the OP.
Such controls need a *pumping* STA thread to run on.
Right. Okay, so in many cases you'd get away with it not entirely
through chance but just by not using the controls which require the
pumping STA.
Now, if you don't initialize your UI thread to enter an STA, the CLR will
initialize the thread to enter the MTA whenever you call into COM for the
first time, that is when you create an instance of say OpenFileDialog. Note
that the v2 SP1 CLR initializes the thread to enter the MTA (if not marked
otherwise) even before it starts the main thread.
Yikes - that sounds like a significant change. My understanding was
that the CLR would only initialize a thread one way or another the
first time a method with STAThread or MTAThread was encountered on that
thread. In other words, your Main method could call something else
which in turn was decorated with STAThread. Am I right in interpreting
your comments to say this isn't the case with the v2 CLR SP1?
FileDialog (the wrapped AX dialog) as all other dialogs, is marked as
requiring an STA, so it can't get instantiated on the calling MTA thread,
COM takes care of this by creating a new thread that gets initialized to
enter an STA and creates the instance of the dialog on this thread and
returns a proxy to the caller.
That mean you'll end with the following (important for this discussion)
threads in a Forms application that doesn't mark it's main UI thread as
STAThread.

Main thread (UI) MTA.
GDI Thread MTA (used by Forms)
STA thread created by COM hosting the FileDialog AX control.
Why is the GDI thread not the main thread? I thought that
Application.Run just ran the message pump on the current thread? Or
does GDI just need two threads anyway, one for message pumping and one
for something else?
So far so good, the control runs on a compatible thread, and the caller
receives a proxy (a marshaled Interface Pointer). The problem however is
that the STA thread created by COM on your behalf isn't pumping messages,
that means that your OpenFileDialog cannot communicate with the callers
thread. The result is that the dialog cannot be used,it will not even
show-up (I guess) and the UI thread deadlocks.
Note also that the Finalizer (MTA) thread cannot access the controls STA
thread whenever he needs to run the Control's Finalize method. This is no
big deal in this scenario, as the control is non-functional anyway, but it's
a big issue when you have to deal with non-visual AX controls.
Right. Thanks for clearing that up. Admittedly it's open up other cans
of worms in terms of my understanding of WinForms, but there we go...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Oct 22 '07 #8

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Willy Denoyette [MVP] <wi*************@telenet.bewrote:
Out of interest, what are the problems one might find without this? For
test purposes I've often created forms which do very little, and rarely
bothered to put the STAThread attribute on them. They've been fine -
but I quite understand that either this was through chance or because I
wasn't using particular components.

A couple of the Windows Forms controls are simple wrappers around ActiveX
COM controls, notably all the "Dialog Controls" are AX control wrappers,
one
of them being the OpenFileDialog as used by the OP.
Such controls need a *pumping* STA thread to run on.

Right. Okay, so in many cases you'd get away with it not entirely
through chance but just by not using the controls which require the
pumping STA.
If you only use controls that are *not* COM based, *and* If you don't use
"cust and paste" support in Windows Forms, which is OLE based (OLE is a COM
based technology), then you can safely ignore the STAThread attribute on
main, but why would you?
The problem is that you can't possibly know which controls are COM based and
which are not, so STATHread is a safe bet when you have to deal with Forms
and V3's WPF.
>Now, if you don't initialize your UI thread to enter an STA, the CLR will
initialize the thread to enter the MTA whenever you call into COM for the
first time, that is when you create an instance of say OpenFileDialog.
Note
that the v2 SP1 CLR initializes the thread to enter the MTA (if not
marked
otherwise) even before it starts the main thread.

Yikes - that sounds like a significant change. My understanding was
that the CLR would only initialize a thread one way or another the
first time a method with STAThread or MTAThread was encountered on that
thread. In other words, your Main method could call something else
which in turn was decorated with STAThread. Am I right in interpreting
your comments to say this isn't the case with the v2 CLR SP1?
The current version of the CLR initilizes COM at the first call into a RCW,
say from the main UI thread. If the main entry is not tagged with a thread
attribute, the RCW will initialize the thread to enter the MTA, else it will
initialize the thread to enter the apartment that is specified by the
attribute.
The problem with the current version is that initializing at first call
might be too late , therefore the CLR team took the decision to initialize
the thread before calling main. That means that the UI thread is always
initialize when main starts executing, and there is no surprise here,
STAThread initializes the thread to enter an STA, all other cases initialize
the thread to enter the MTA.

>FileDialog (the wrapped AX dialog) as all other dialogs, is marked as
requiring an STA, so it can't get instantiated on the calling MTA thread,
COM takes care of this by creating a new thread that gets initialized to
enter an STA and creates the instance of the dialog on this thread and
returns a proxy to the caller.
That mean you'll end with the following (important for this discussion)
threads in a Forms application that doesn't mark it's main UI thread as
STAThread.

Main thread (UI) MTA.
GDI Thread MTA (used by Forms)
STA thread created by COM hosting the FileDialog AX control.

Why is the GDI thread not the main thread? I thought that
Application.Run just ran the message pump on the current thread? Or
does GDI just need two threads anyway, one for message pumping and one
for something else?
GDI creates and manages it's own thread, this is not a CLR thread , it
becomes a CLR thread when this thread calls back into the main thread.

>So far so good, the control runs on a compatible thread, and the caller
receives a proxy (a marshaled Interface Pointer). The problem however is
that the STA thread created by COM on your behalf isn't pumping messages,
that means that your OpenFileDialog cannot communicate with the callers
thread. The result is that the dialog cannot be used,it will not even
show-up (I guess) and the UI thread deadlocks.
Note also that the Finalizer (MTA) thread cannot access the controls STA
thread whenever he needs to run the Control's Finalize method. This is
no
big deal in this scenario, as the control is non-functional anyway, but
it's
a big issue when you have to deal with non-visual AX controls.

Right. Thanks for clearing that up. Admittedly it's open up other cans
of worms in terms of my understanding of WinForms, but there we go...
Well, I guess it's just a matter of respecting a number of simple rules
(this is in general what Software development is all about), if you don't
then you better know what's going on under the covers.

Willy.

Oct 22 '07 #9

P: n/a
Willy Denoyette [MVP] <wi*************@telenet.bewrote:
Right. Okay, so in many cases you'd get away with it not entirely
through chance but just by not using the controls which require the
pumping STA.

If you only use controls that are *not* COM based, *and* If you don't use
"cust and paste" support in Windows Forms, which is OLE based (OLE is a COM
based technology), then you can safely ignore the STAThread attribute on
main, but why would you?
In my case it's simply been forgetfulness for throwaway apps.
The problem is that you can't possibly know which controls are COM based and
which are not, so STATHread is a safe bet when you have to deal with Forms
and V3's WPF.
Fair enough.
Yikes - that sounds like a significant change. My understanding was
that the CLR would only initialize a thread one way or another the
first time a method with STAThread or MTAThread was encountered on that
thread. In other words, your Main method could call something else
which in turn was decorated with STAThread. Am I right in interpreting
your comments to say this isn't the case with the v2 CLR SP1?

The current version of the CLR initilizes COM at the first call into a RCW,
say from the main UI thread. If the main entry is not tagged with a thread
attribute, the RCW will initialize the thread to enter the MTA, else it will
initialize the thread to enter the apartment that is specified by the
attribute.
The problem with the current version is that initializing at first call
might be too late , therefore the CLR team took the decision to initialize
the thread before calling main. That means that the UI thread is always
initialize when main starts executing, and there is no surprise here,
STAThread initializes the thread to enter an STA, all other cases initialize
the thread to enter the MTA.
Hmm... that still sounds like a breaking change where previously you
might have had:

Main (no attribute) calling...
StartUI (STAThread) calling...
OtherStuff

I *think* that would have previously used an STAThread, but is now
using an MTAThread (and is therefore incorrect). Or am I just wrong
about it previously using an STAThread in that case?
Main thread (UI) MTA.
GDI Thread MTA (used by Forms)
STA thread created by COM hosting the FileDialog AX control.
Why is the GDI thread not the main thread? I thought that
Application.Run just ran the message pump on the current thread? Or
does GDI just need two threads anyway, one for message pumping and one
for something else?

GDI creates and manages it's own thread, this is not a CLR thread , it
becomes a CLR thread when this thread calls back into the main thread.
Blick. Hopefully Joe Duffy's new book will explain all this when it
comes out :) I'm woefully uninformed when it comes to WinForms
threading. General threading principles I'm fine with, but this is
somewhat different.
Right. Thanks for clearing that up. Admittedly it's open up other cans
of worms in terms of my understanding of WinForms, but there we go...

Well, I guess it's just a matter of respecting a number of simple rules
(this is in general what Software development is all about), if you don't
then you better know what's going on under the covers.
True.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Oct 22 '07 #10

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Willy Denoyette [MVP] <wi*************@telenet.bewrote:
Right. Okay, so in many cases you'd get away with it not entirely
through chance but just by not using the controls which require the
pumping STA.

If you only use controls that are *not* COM based, *and* If you don't
use
"cust and paste" support in Windows Forms, which is OLE based (OLE is a
COM
based technology), then you can safely ignore the STAThread attribute on
main, but why would you?

In my case it's simply been forgetfulness for throwaway apps.
No big deal in this case, as long as you keep in mind that in case of a
Forms application, that you are creating at least one additional thread
possibly two, that means 1 or 2MB additional stack space used (4 or 8MB on
X64).

>The problem is that you can't possibly know which controls are COM based
and
which are not, so STATHread is a safe bet when you have to deal with
Forms
and V3's WPF.

Fair enough.
Yikes - that sounds like a significant change. My understanding was
that the CLR would only initialize a thread one way or another the
first time a method with STAThread or MTAThread was encountered on that
thread. In other words, your Main method could call something else
which in turn was decorated with STAThread. Am I right in interpreting
your comments to say this isn't the case with the v2 CLR SP1?

The current version of the CLR initilizes COM at the first call into a
RCW,
say from the main UI thread. If the main entry is not tagged with a
thread
attribute, the RCW will initialize the thread to enter the MTA, else it
will
initialize the thread to enter the apartment that is specified by the
attribute.
The problem with the current version is that initializing at first call
might be too late , therefore the CLR team took the decision to
initialize
the thread before calling main. That means that the UI thread is always
initialize when main starts executing, and there is no surprise here,
STAThread initializes the thread to enter an STA, all other cases
initialize
the thread to enter the MTA.

Hmm... that still sounds like a breaking change where previously you
might have had:

Main (no attribute) calling...
StartUI (STAThread) calling...
OtherStuff

I *think* that would have previously used an STAThread, but is now
using an MTAThread (and is therefore incorrect). Or am I just wrong
about it previously using an STAThread in that case?
I'm afraid you are wrong here , the main thread is "non-initialized" at the
start of an non-attributed Main, such main thread initializes to enter the
MTA whenever some code running in this thread calls into COM.
The only difference is that now(V2 SP1), the main thread will enter an STA
when the attribute is set, else it enters the MTA, *before* calling Main.

>Main thread (UI) MTA.
GDI Thread MTA (used by Forms)
STA thread created by COM hosting the FileDialog AX control.

Why is the GDI thread not the main thread? I thought that
Application.Run just ran the message pump on the current thread? Or
does GDI just need two threads anyway, one for message pumping and one
for something else?

GDI creates and manages it's own thread, this is not a CLR thread , it
becomes a CLR thread when this thread calls back into the main thread.

Blick. Hopefully Joe Duffy's new book will explain all this when it
comes out :) I'm woefully uninformed when it comes to WinForms
threading. General threading principles I'm fine with, but this is
somewhat different.
I don't know whether Joe will talk about this unmanaged GDI++ stuff, note
that Windows Forms has some more (unmanaged) thread magic going on under
the covers, especially when you are calling into OLE stuff or AX controls
(like Dialogs) from a wrong (non STA) thread.

Right. Thanks for clearing that up. Admittedly it's open up other cans
of worms in terms of my understanding of WinForms, but there we go...

Well, I guess it's just a matter of respecting a number of simple rules
(this is in general what Software development is all about), if you don't
then you better know what's going on under the covers.

True.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Willy.

Oct 22 '07 #11

P: n/a
Willy Denoyette [MVP] <wi*************@telenet.bewrote:

<snip>
Hmm... that still sounds like a breaking change where previously you
might have had:

Main (no attribute) calling...
StartUI (STAThread) calling...
OtherStuff

I *think* that would have previously used an STAThread, but is now
using an MTAThread (and is therefore incorrect). Or am I just wrong
about it previously using an STAThread in that case?
I'm afraid you are wrong here , the main thread is "non-initialized" at the
start of an non-attributed Main, such main thread initializes to enter the
MTA whenever some code running in this thread calls into COM.
The only difference is that now(V2 SP1), the main thread will enter an STA
when the attribute is set, else it enters the MTA, *before* calling Main.
Let me clarify - because I now believe I was wrong, but I may also have
put it badly before :)

I thought it would be uninitialized during Main, but on the call to
StartUI (decorated with the STAThread attribute) it would become
initialized as STA.

Now I've just read in the STAThreadAttribute this bit:

<quote>
Apply this attribute to the entry point method (the Main() method in C#
and Visual Basic). It has no effect on other methods.
</quote>

That proves me wrong pretty categorically. Thanks for being patient
with my ignorance :)
GDI creates and manages it's own thread, this is not a CLR thread , it
becomes a CLR thread when this thread calls back into the main thread.
Blick. Hopefully Joe Duffy's new book will explain all this when it
comes out :) I'm woefully uninformed when it comes to WinForms
threading. General threading principles I'm fine with, but this is
somewhat different.

I don't know whether Joe will talk about this unmanaged GDI++ stuff, note
that Windows Forms has some more (unmanaged) thread magic going on under
the covers, especially when you are calling into OLE stuff or AX controls
(like Dialogs) from a wrong (non STA) thread.
Right. I'd be surprised if he left it out entirely - but we'll have to
see. It's definitely on my "must buy" list.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Oct 22 '07 #12

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Willy Denoyette [MVP] <wi*************@telenet.bewrote:

<snip>
Hmm... that still sounds like a breaking change where previously you
might have had:

Main (no attribute) calling...
StartUI (STAThread) calling...
OtherStuff

I *think* that would have previously used an STAThread, but is now
using an MTAThread (and is therefore incorrect). Or am I just wrong
about it previously using an STAThread in that case?
I'm afraid you are wrong here , the main thread is "non-initialized" at
the
start of an non-attributed Main, such main thread initializes to enter
the
MTA whenever some code running in this thread calls into COM.
The only difference is that now(V2 SP1), the main thread will enter an
STA
when the attribute is set, else it enters the MTA, *before* calling Main.

Let me clarify - because I now believe I was wrong, but I may also have
put it badly before :)
Maybe I wasn't clear when explaining ;-)
I thought it would be uninitialized during Main, but on the call to
StartUI (decorated with the STAThread attribute) it would become
initialized as STA.
A decorated Main (On a pre-SP1) gets initialized (STA or MTA) just before
the CLR calls Main. A non-decorated Main gets MTA initialized by Forms code
(when calling into COM).
On SP1 the CLR initializes the thread quite a bit before calling Main. A
non-decorated Main enters the MTA, a decorated Main gets initialized
depending it's attribute value. In short, on SP1 you are certain that your
Main function is initialized on entry.
Right. I'd be surprised if he left it out entirely - but we'll have to
see. It's definitely on my "must buy" list.
Lets hope it doesn't take that that long or we will have to write something
ourselves :-), anyway I have it on my list too.

Willy.
Oct 22 '07 #13

This discussion thread is closed

Replies have been disabled for this discussion.