I'll concede there is a difference in responsiveness of the GUI when making a blocking cross-apartment COM call with STAThread and MTAThread. STAThread will be *more* responsive than MTAThread--STAThread will repaint but the title may append "(Not Responding)". The "GUI Thread" will still be blocked. The application will not get any more GUI events while blocked on that COM method (there are exceptions; but, this is the general case). But, any other type of call that is blocking will not repaint the GUI.
I try and clarify my comment on one thread in STA: an application can start any number of threads it wants in an STA; but, only one thread should do any COM interop (I don't know if "at a time" is valid; but it certainly wouldn't be safe). If you want more than one of your threads to do COM interop they better be in an MTA or deadlocks may ensue (assuming you're communicating with any particular STA object on only one of your threads). If we get back to the original question regarding WaitHandle.WaitAll() and your suggestion that a WinForm application should never be anything other than STAThread: This suggests that WaitHandle.WaitAll cannot be used with a WinForm application (without, of course, starting up another thread apartment, as MTA, and using WaitHandle.WaitOne to wait for that MTA thread. But, as Chris Brumme points out on his blog [1], this is a bad idea). My assumption was that the application did not use COM (which has neither been confirmed nor denied) and the application needed to wait for more than one synchronization object at a time. In this case, MTAThread will not affect the application other than the effect of enabling WaitAll(). I'm avoiding going OT by discussing a WinForm application that spawns multiple threads to use COM interop to communicate with more than one MTA COM object. But, it would be an interesting discussion. [1] http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx http://www.peterRitchie.com/ On Fri, 23 Sep 2005 13:30:51 -0700, Russ Alan <[EMAIL PROTECTED]> wrote: >I agree with that description of STA. On the "single thread" comment, I was >referring to this from your earlier reply. > ><quote> >"you're telling the runtime, from a COM interop perspective, that your >application has only one thread" ></quote> > >And putting the GUI thread in the MTA does have an affect on the UI windows >since a call out of apartment will block the calling thread on the "send". >When you call out of a STA, the default COM infrastructure (channel) >continues to pump messages while pseudo blocked in the call. This keeps the >UI thread responsive. And that is where the "COM message pumps" come in, >during a call out of apt from a STA. The destination apt type is irrelevant >to this point. > >That is the connection between GUI threads and COM, and there is nothing >(realistically) that the runtime can do to change that connection. And that >is why your main thread in a WinForms app should never be anything other >than a STA thread. Making it an MTA thread means that "free" objects >created in the MTA are accessed directly (baring COM+ contexts) and may very >well use blocking at any time (maybe infinite blocking on a socket read?) >AND that calls out of apt will block the thread for an indeterminate amount >of time (until the call returns). > >Russ > >-----Original Message----- >From: Unmoderated discussion of advanced .NET topics. >[mailto:[EMAIL PROTECTED] On Behalf Of Peter Ritchie >Sent: Friday, September 23, 2005 12:14 PM >To: ADVANCED-DOTNET@DISCUSS.DEVELOP.COM >Subject: Re: [ADVANCED-DOTNET] WaitHandle.WaitAll STA thread. > > >No offence taken. STA means "single thread". I never said "only one >thread"; but, single means one. STA means one thread per apartment. If you >create another thread from an STA thread you're creating another apartment. >An STA has no "direct" access to anything in another apartment- -it is >*always* marshaled. There will be a performance hit for apartment- >to-apartment communications (which may or may not be noticeable/important). > >I think you're confusing the GUI thread(s) and COM STA and MTA. Declaring a >WinForm application MTAThread (or STAThread) as no direct affect on >responsiveness of the UI. Jeff Prosise has a good article on COM apartments >at http://www.codeguru.com/Cpp/COM- Tech/activex/apts/article.php/c5529/ > >An application has a UI message pump and the OS has one or more COM message >pumps--unless the application does its own marshaling; which is very rare. > >In a WinForm application, if you create no extra threads and make a call to >another apartment (regardless of whether that apartment is MTA or STA), >you're making that call on the GUI thread and *will* be blocked until that >call returns and *will* affect the responsiveness of your UI. If your one- >and-only thread is blocked it cannot process COM requests. The OS deals >with the "messages" and simply marshals data and calls your interfaces. > >MTA and STA really doesn't have any bearing on a .NET app unless you're >dealing with COM objects, or try to have different apartments communicate >via COM. > >On Fri, 23 Sep 2005 10:39:17 -0700, Russ Alan <[EMAIL PROTECTED]> wrote: > >>No offense, but this is not correct. >> >>STA does not mean "only one thread". An application can have numerous >>STA threads. STA means that only one thread is used to execute through >>objects/code that are in the "apartment" AND that the thread WILL/MUST >pump >>messages (i.e. it can NOT block). STA is necessary for direct access >>(or rather to have any chance of) to "apartment" threaded objects. >>It's also necessary if you create windows using that thread. For >>example, the main thread of a WinForm app... >> >>When you call out of an STA, the COM infrastructure continues to pump >>messages to keep your UI responsive. If it did not, you're window(s) >would >>not repaint and you could get into a deadlock situation rather easily. >>Of course that introduces reentrancy into the STA too, but that's >>another topic... >> >>So bottom line is you can't *block* an STA thread because STA threads >>are required to process messages. And you can't change a WinForm >>thread to >MTA. >>However, you CAN spawn new threads in a WinForm App that do not >>directly create or manipulate WinForm elements and make THOSE threads >>MTA threads >(or >>don't set MTA or STA if you don't use COM directly or indirectly on >>that thread). >> >>IIRC, you will need to pinvoke MsgWaitForMultipleObjectsEx to properly >sync >>your STA/WinForm thread. >> >>Russ >> >>-----Original Message----- >>From: Unmoderated discussion of advanced .NET topics. >>[mailto:[EMAIL PROTECTED] On Behalf Of Peter Ritchie >>Sent: Friday, September 23, 2005 6:42 AM >>To: ADVANCED-DOTNET@DISCUSS.DEVELOP.COM >>Subject: Re: [ADVANCED-DOTNET] WaitHandle.WaitAll STA thread. >> >> >>Of course you can change STAThread to MTAThread. If you make use of >>any free-threaded COM objects you would have to change STAThread to >>MTAThread that anyway. If you use the ThreadPool you'd probably also >>want to switch to a multi-threaded apartment. >> >>STAThread is documented as only affecting COM interop interactions. >>This >is >>obviously not true, it also affects (at least) WaitHandle.WaitAll >(). .NET >>applications default to STAThread as a least-privileges principle, as >>you >>(normally) manually start multiple threads. I guess you're magically >>supposed to know the importance of MTAThread when you spawn extra threads >or >>use WaitAll(). If you're not spawning any extra threads MTAThread will >only >>affect WaitAll() and COM interactions. >> >>To ensure you cannot get any external calls to your assembly via COM >>you >can >>add the COMVisible(false) attribute to your assembly, which I believe >>what FxCop suggests by default. >> >>If you're not using COM (you can ignore the rest of this, in that >>case), using MTAThread will not affect how you must design your >>application to >deal >>with synchronization during incoming calls to your apartment via your >>COM interface, other than typical threading synchronization issues. >>With a multi-threaded apartment COM calls from outside or to outside >>the >apartment >>are still blocking, calls between COM objects *within* the multi- >>threaded apartment are not blocking and not marshaled--which is where >>the extra synchronization comes in. If you created a single-threaded >>apartment >within >>your process, it too would have all incoming calls marshaled and >>blocked, even if they came from the multi-threaded apartment. >> >>If you make your assembly or any of it's methods COMVisible, or start >>creating new apartments within your process, or give any COM interfaces >to a >>free-threaded apartment; you'll have to revisit synchronization design >>of your application. >> >>http://www.peterRitchie.com/ >> >>On Fri, 23 Sep 2005 08:55:58 -0400, Allan N. <[EMAIL PROTECTED]> wrote: >> >>>Hi Peter, >>>are you telling me I can simply change my sta to mta on my Winform ? >>> >>>I was under the impression that this was a no no.... >>> >>>cheers Allan >>> >>>On Fri, 23 Sep 2005 08:48:42 -0400, Peter Ritchie >>><[EMAIL PROTECTED]> wrote: >>> >>>>For specific check out: >>>>http://blogs.msdn.com/cbrumme/archive/2004/02/02/66219.aspx >>>> >>>>For what it's worth, when I changed STAThread to MTAThread WaitAll >>>>worked fine, as expected. >>>> >>>>http://www.peterRitchie/ >>>> >>>>On Fri, 23 Sep 2005 05:28:28 -0400, Allan N. <[EMAIL PROTECTED]> wrote: >>>> >>>>>Hi, >>>>>in my naive attempt to spin off 6 threads and then wait for them to >>>finish >>>>>before filling a grid I got the >>>>>"WaitAll for multiple handles on an STA thread is not supported" >>>>>message flashing in my eyes. >>>>> >>>>>checking the documentation was perhaps the best I could have done >>>>>before going this way :). >>>>> >>>>>what else could I use here instead of WaitAll ? using >>>>>ManualResetEvent [curThread].WaitOne and then looping seems rather >>>>>tedious... =================================== This list is hosted by DevelopMentorĀ® http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com