.NET Forum / Languages / C# / March 2008
Not using [STAThread]
|
|
Thread rating:  |
K Viltersten - 15 Mar 2008 20:51 GMT I see that VS by default pops in the statement [STAThread] in the code and since i started with all-blank-project this time, the part was missing.
Nevertheless, the program works and is happy. So i wonder - what's that good for?
Is it something internal for VS or is it a part of C#?
-- Regards Konrad Viltersten -------------------------------- sleep - a substitute for coffee for the poor ambition - lack of sense to be lazy
Arne Vajhøj - 15 Mar 2008 21:00 GMT > I see that VS by default pops in the > statement [STAThread] in the code and since [quoted text clipped - 5 lines] > Is it something internal for VS or is it a > part of C#? http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx http://www.sellsbrothers.com/askthewonk/Secure/WhatdoestheSTAThreadattri.htm http://www.codeguru.com/forum/showthread.php?t=407960 etc.
Arne
Peter Duniho - 15 Mar 2008 21:06 GMT > I see that VS by default pops in the > statement [STAThread] in the code and since [quoted text clipped - 5 lines] > Is it something internal for VS or is it a > part of C#? It's related to .NET and how it uses COM. It signals to the compiler to cause the thread executing that method (Main(), in the case of the VS templates) to be initialize itself as a "single-threaded apartment" thread.
If the thread never actually uses COM, then you don't need it. You don't describe any details about your project, so whether it's a bug to not include that attribute (not statement) in your code, I can't say. For a Forms-based Windows application though, it should be there. For a console application, it's not necessarily needed.
Pete
K Viltersten - 15 Mar 2008 21:21 GMT >> I see that VS by default pops in the >> statement [STAThread] in the code and since [quoted text clipped - 16 lines] > Forms-based Windows application though, it should be there. For a console > application, it's not necessarily needed. Thanks to both. Yes, i'm doing the console this time, so it's probably the reason. Nevertheless, i'll put it in, just for the sake of future sanity. :)
 Signature -- Regards Konrad Viltersten -------------------------------- sleep - a substitute for coffee for the poor ambition - lack of sense to be lazy
Peter Duniho - 15 Mar 2008 23:24 GMT > Thanks to both. Yes, i'm doing the console this time, > so it's probably the reason. Nevertheless, i'll put it in, > just for the sake of future sanity. :) I wouldn't, if I were you. AFAIK, a normal console application never actually has to initialize COM. By putting that attribute in, you cause COM to be initialized. At a minimum, this is a waste. Additionally, doing so in a console application could interfere with garbage collection (I just found this doing a search on MSDN: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=16154&SiteID=1).
Basically, unless you have a specific need to explicitly specify the apartment model, don't.
Pete
K Viltersten - 15 Mar 2008 23:38 GMT >> Thanks to both. Yes, i'm doing the console this time, >> so it's probably the reason. Nevertheless, i'll put it in, [quoted text clipped - 8 lines] >Basically, unless you have a specific need to explicitly specify the >apartment model, don't. Great info. Thanks!
-- Regards Konrad Viltersten -------------------------------- sleep - a substitute for coffee for the poor ambition - lack of sense to be lazy
Jon Skeet [C# MVP] - 15 Mar 2008 23:41 GMT > > Thanks to both. Yes, i'm doing the console this time, > > so it's probably the reason. Nevertheless, i'll put it in, [quoted text clipped - 3 lines] > actually has to initialize COM. By putting that attribute in, you cause > COM to be initialized. Are you sure? I thought it just initialized the thread in a way which allowed STA COM components to be used later. I've certainly used it in the past with no ill effects.
> At a minimum, this is a waste. Additionally, > doing so in a console application could interfere with garbage collection > (I just found this doing a search on MSDN: > http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=16154&SiteID=1). It sounds like in that case there *was* COM involved though.
> Basically, unless you have a specific need to explicitly specify the > apartment model, don't. I guess the only worry is if you really don't know whether the underlying .NET code is going to use COM at some point. I think this is a significant problem - it's really not terribly obvious which APIs beyond some (but not all?) WinForm controls use COM under the hood.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Peter Duniho - 16 Mar 2008 00:40 GMT >> I wouldn't, if I were you. AFAIK, a normal console application never >> actually has to initialize COM. By putting that attribute in, you cause [quoted text clipped - 3 lines] > allowed STA COM components to be used later. I've certainly used it in > the past with no ill effects. Am I sure? No...that's why I wrote "AFAIK" (i.e. "as far as I know"). However, normally the way you initialize a thread's apartment state is to pass the appropriate flag, either COINIT_APARTMENTTHREADED or COINIT_MULTITHREADED, when calling CoInitializeEx().
If the .NET is somehow using that attribute to turn it into a call to CoInitializeEx() (and I would expect it to), then using the attribute would thus imply an initialization of COM.
>> At a minimum, this is a waste. Additionally, >> doing so in a console application could interfere with garbage [quoted text clipped - 3 lines] > > It sounds like in that case there *was* COM involved though. Right. My reading of the post is that the leak happened because COM was involved and being used inappropriately. The point here is that the OP is suggesting that he'll put that attribute in now, "just in case", but in fact if and when it actually becomes relevant, it could actually _hurt_ to have a single-threaded apartment rather than help.
In other words, at the time that the attribute becomes relevant, the OP had better be making a conscious decision about which apartment model to use and given that, they will have every opportunity to add the correct attribute at that time. Until that time, it isn't adding anything useful, and could very well lead to loading COM into the process when it wasn't necessary.
For what it's worth, I ran a quick test, modifying an existing console application I had lying around by adding the [STAThread] attribute to the Main() method. Comparing the loaded DLL's for the process between the two instances, the one with the attribute had three extra DLLs: MSCTF.DLL, UXTHEME.DLL, and PRLHOOK.DLL. The last one is particular to my Windows installation (the description is "Parallels Helper Hook", so presumably it got loaded as a side-effect of one of the other DLLs and because I'm running Windows in a VM), but I'd guess the other two would show up on anyone's computer.
I admit, even after some quick Googling, I don't have an explanation for _why_ those particular DLLs get sucked in when STAThread is specified. They don't seem directly related to COM per se. But I can confirm there's a definite difference in how the process executes even if all you've done is add that attribute.
So, again: I would not add it until such point in time if and when it is actually needed. It's not going to help anything, and it could be detrimental.
Pete
Jon Skeet [C# MVP] - 16 Mar 2008 08:29 GMT > >> I wouldn't, if I were you. AFAIK, a normal console application never > >> actually has to initialize COM. By putting that attribute in, you cause [quoted text clipped - 5 lines] > > Am I sure? No...that's why I wrote "AFAIK" (i.e. "as far as I know"). Well, to be picky that was in the sentence saying that you didn't have to initialize COM - the following sentence sounded more confident :)
> However, normally the way you initialize a thread's apartment state is to > pass the appropriate flag, either COINIT_APARTMENTTHREADED or [quoted text clipped - 3 lines] > CoInitializeEx() (and I would expect it to), then using the attribute > would thus imply an initialization of COM. Interestingly, the docs for STAThreadAttribute say:
<quote>
> >> At a minimum, this is a waste. Additionally, > >> doing so in a console application could interfere with garbage [quoted text clipped - 38 lines] > > Pete
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Jon Skeet [C# MVP] - 16 Mar 2008 08:35 GMT (Apologies if the first bit of this comes through twice.)
> >> I wouldn't, if I were you. AFAIK, a normal console application never > >> actually has to initialize COM. By putting that attribute in, you cause [quoted text clipped - 5 lines] > > Am I sure? No...that's why I wrote "AFAIK" (i.e. "as far as I know"). Well, to be picky that was in the sentence saying that you didn't have to initialize COM - the following sentence sounded more confident :)
> However, normally the way you initialize a thread's apartment state is to > pass the appropriate flag, either COINIT_APARTMENTTHREADED or [quoted text clipped - 3 lines] > CoInitializeEx() (and I would expect it to), then using the attribute > would thus imply an initialization of COM. Interestingly, the docs for STAThreadAttribute say:
<quote> The COM threading model can be set to single-threaded apartment or multithreaded apartment. The application thread is only initialized for COM interop if the thread actually makes a call to a COM component. If COM interop is not used, then the thread is not initialized. </quote>
(I hadn't seen that before this post, btw.)
I *hope* it's accurate, but you never know...
> >> At a minimum, this is a waste. Additionally, > >> doing so in a console application could interfere with garbage [quoted text clipped - 9 lines] > fact if and when it actually becomes relevant, it could actually _hurt_ to > have a single-threaded apartment rather than help. Yes, that's true. Just to be clear though, I think we both agree that it's not going to hurt garbage collection when COM *isn't* involved.
> In other words, at the time that the attribute becomes relevant, the OP > had better be making a conscious decision about which apartment model to > use and given that, they will have every opportunity to add the correct > attribute at that time. Until that time, it isn't adding anything useful, > and could very well lead to loading COM into the process when it wasn't > necessary. That's reasonable. There's still the issue of what happens when COM unwittingly gets dragged in - but that will be an issue either way.
<snip dll stuff, purely because I don't have anything to say about it>
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Peter Duniho - 16 Mar 2008 09:21 GMT > Interestingly, the docs for STAThreadAttribute say: > [quoted text clipped - 8 lines] > > I *hope* it's accurate, but you never know... Sure, I'd hope it's accurate too. But I've seen too many inaccurate statements in the docs to be confident that it is.
Especially since when I compared two different console applications, the only difference between the two being the presence of the STAThread attribute in one, and saw that the one with the STAThread attribute does in fact load additional DLLs, I become somewhat more confident that I can't trust MSDN on this one.
I don't have a good explanation for why the particular DLLs that got loaded did in fact get loaded. But I know for sure that they did, and I know for sure that it's a stable behavior (that is, add the attribute, they show up, remove the attribute, they go away).
Even if the behavior was different on someone else's computer, it's clear to me that that attribute is doing more, even when COM isn't explicitly involved, than just setting some flag in the managed thread for the COM interop to look at if it ever gets invoked.
Something is _executing_ differently, even when COM isn't used (or else it turns out that there's no such thing as a .NET console application that doesn't use COM...all I know is the console application was a trivial "print this float" program, and for all I know .NET _is_ in fact using COM for some reason, but if so that's even more reason to be concerned, since it means COM gets used implicitly for the most trivial programs).
> Yes, that's true. Just to be clear though, I think we both agree that > it's not going to hurt garbage collection when COM *isn't* involved. Well, I do agree with that statement. The problem is, though, that I can't qualify "involved" with "explicitly". My experiment shows me that something different happens with that attribute. It _might_ be that COM gets used implicitly, in which case there could still be a garbage collection issue. Or it could just be that .NET is loading extra DLLs without actually using COM past that point, in which case I think it's likely that wouldn't cause the GC issue to show up.
But I don't have any practical way to know the difference. I mean, if I really cared I suppose I could research this and track down the actual answer. But I don't, especially since I think there's already other good reasons to leave off the attribute unless it's actually needed. So I just put that data in the "one more reason not to include the attribute" column. :)
Pete
Willy Denoyette [MVP] - 16 Mar 2008 12:47 GMT > (Apologies if the first bit of this comes through twice.) > [quoted text clipped - 32 lines] > > I *hope* it's accurate, but you never know... Well, it's not accurate a all. Actually, when the (STA/MTA) attribute is set on Main, then COM gets initialized *before* entering main, that is, ole32!CoInitializeEx is called by the CLR before it enters managed code. When the attribute is not set, and the thread is not initialized explicitly , then the CLR will initialize the thread to join the MTA when calling into COM for the first time.
To resume: You have to set the STA/MTA attribute whenever you want to force your main thread (your program's entry point) to run in a compatible apartment. Calling into COM from a compatible apartment is the most effective way to call into COM, as there is no need to marshal the calls across incompatible apartments. For Windows Forms, the compatible apartment is STA, the reason for this is that WF needs an STA for drag/drop functionality and because a number of controls are COM based and need an STA apartment to function properly
A console application doesn't need the attribute, unless it explicitly calls into COM from it's main thread. A console application that sets it's main thread to enter an STA, must pump a message queue. This is not only a .NET requirement (finalizer thread), it's a general COM requirement. A console application that sets it's main thread to enter the MTA, does not need a message pump.
Willy.
>> >> At a minimum, this is a waste. Additionally, >> >> doing so in a console application could interfere with garbage [quoted text clipped - 27 lines] > > <snip dll stuff, purely because I don't have anything to say about it> Jon Skeet [C# MVP] - 16 Mar 2008 13:26 GMT <snip>
> Well, it's not accurate a all. Thanks for clearing up the confusion. I was kinda hoping you'd step in at some point as resident COM expert :)
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Willy Denoyette [MVP] - 16 Mar 2008 16:26 GMT > <snip> > >> Well, it's not accurate a all. > > Thanks for clearing up the confusion. I was kinda hoping you'd step in > at some point as resident COM expert :) The problem is that once you start to document "implementation details", you also need to update the docs whenever *the* implementation changes. In this particular case the docs were not updated after V1.1 changed the point where COM was initialized. In general (and in this case), this is a non-issue, such changes do not affect your code, but there may be others.....
Willy.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|