ThreadPool and COM+

D

Duane Pressley

I'm looking for someone to help me make sense of the results I'm observing when using the ThreadPool class in a COM-Interop scenario. Here's the set up:
1.. A classic ASP page instantiates and calls MethodA on COM+ Class (C1).
2.. MethodA of COM+ class (C1) instantiates and calls MethodB of .NET class (N1). (Note: N1 has been registered using RegASM and is present in the GAC).
3.. MethodB of .NET class (N1) uses the ThreadPool.QueueUserWorkItem method to queue up a call to MethodC on .NET Class (N2).
4.. MethodC of .NET Class (N2), (called on a ThreadPool thread), instantiates and calls MethodD on COM+ class (C2).
5.. MethodD of COM+ Class (C2) instantiates and calls MethodE on COM+ class (C3).
6.. Finally, methodB of .NET Class (N1) uses static members of .NET Class (N2) to retrieve the results of the "background" processing. These results are passed back to COM+ Class (C1) and ultimately displayed on the ASP page.
Note: All COM+ classes are registered within the same COM+ application; and this application is configured as a "Library" application.

I believe this sequence of calls results in the following transitions:
1.. An IIS worker thread, (running C1), transitions to .NET managed thread, (running N1). I'm not at all clear as to what process owns the ..NET thread.
2.. As a result of item#1 a .NET ThreadPool thread, (running N2), transitions to a COM+ thread, (running C2).
3.. I'm assuming the same COM+ Thread from item#2 is used to run C3.
4.. The COM+ Thread running C2 and C3 completes and transitions back to the .NET ThreadPool thread running N2.
5.. Based on a flag exposed as a static member of N2, the "original" ..NET Thread begins accessing static members of N2. (These static members are used to aggregate results across multiple ThreadPool threads.)
6.. Finally, the "original" .NET thread transitions back to the IIS worker thread running C1.
After modifying Machine.Config such that the "ProcessModel" tag used the "system" account instead of the "machine" account, I was able to get this working in Debug mode. The modification was required to enable transition #2 (listed above). Prior to making this modification an exception was thrown indicating an inability to call COM+ class C2. (Sorry, I don't recall the exact exception.)

When I say Debug mode, I'm referring to running the code within the VS.NET and VS6 IDEs and stepping between break points.

With everything working in Debug mode, I then attempted to execute the code without debugging. Based on well placed App.LogEvent and EventLog.WriteEntry calls, it appears that the following is occurring:
1.. All calls prior to the calling of COM+ Class C3 appear to be working.
2.. The Call to COM+ Class C3 doesn't raise a COM+ error, but the variant returned from this call is empty. During successful execution the resulting variant contains an array with a "UBound" of 5. The real puzzling thing about this situation is that an error with COM+ class C3 should result in a variant containing an array with a "UBound" of 3. There should always be an array returned from COM+ C3!
So the questions are as follows:
1.. Is it possible that the return values, (which are passed ByRef), aren't being marshalled properly between COM+ Class C2 and COM+ Class C3?
2.. Is it possible that the call from COM+ Class C2 to COM+ Class C3 is failing silently? (Placing App.LogEvent calls within COM+ Class C3 requires the involvement of another team.)
3.. Is there some security or thread related issue here that I'm just not seeing? And does this underlying issue explain why things work during Debug and fail when not running under an IDE managed thread?
Thanks for taking the time to read all of that. :)
 
N

Nicholas Paldino [.NET/C# MVP]

Duane,

I believe that there is a threading issue here that could be
contributing to some of the issues you are seeing. The threads in the
ThreadPool class do not belong to any COM compartment by default. This is a
big issue, because components that derive from ServicedComponent are not
free-threaded. From the section of the .NET framework documentation titled
"Managed and Unmanaged Threading in Microsoft Windows":

Managed objects that are exposed to COM behave as if they had aggregated the
free-threaded marshaler. In other words, they can be called from any COM
apartment in a free-threaded manner. The only managed objects that do not
exhibit this free-threaded behavior are those objects that derive from
ServicedComponent.

Since you declared that your components are COM+ components, I'm
assuming they are all derived from ServicedComponent.

Because the apartment is not set up correctly, you probably are not
getting the correct context for your components, which can result in a
number of the issues that you are seeing.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- casper(1 spelled out){at)caspers(where I live, rhymes with
mouse)<dot]com

I'm looking for someone to help me make sense of the results I'm observing
when using the ThreadPool class in a COM-Interop scenario. Here's the set
up:
A classic ASP page instantiates and calls MethodA on COM+ Class (C1).
MethodA of COM+ class (C1) instantiates and calls MethodB of .NET class
(N1). (Note: N1 has been registered using RegASM and is present in the GAC).
MethodB of .NET class (N1) uses the ThreadPool.QueueUserWorkItem method to
queue up a call to MethodC on .NET Class (N2).
MethodC of .NET Class (N2), (called on a ThreadPool thread), instantiates
and calls MethodD on COM+ class (C2).
MethodD of COM+ Class (C2) instantiates and calls MethodE on COM+ class
(C3).
Finally, methodB of .NET Class (N1) uses static members of .NET Class (N2)
to retrieve the results of the "background" processing. These results are
passed back to COM+ Class (C1) and ultimately displayed on the ASP page.
Note: All COM+ classes are registered within the same COM+ application;
and this application is configured as a "Library" application.

I believe this sequence of calls results in the following transitions:
An IIS worker thread, (running C1), transitions to .NET managed thread,
(running N1). I'm not at all clear as to what process owns the .NET thread.
As a result of item#1 a .NET ThreadPool thread, (running N2), transitions to
a COM+ thread, (running C2).
I'm assuming the same COM+ Thread from item#2 is used to run C3.
The COM+ Thread running C2 and C3 completes and transitions back to the .NET
ThreadPool thread running N2.
Based on a flag exposed as a static member of N2, the "original" .NET Thread
begins accessing static members of N2. (These static members are used to
aggregate results across multiple ThreadPool threads.)
Finally, the "original" .NET thread transitions back to the IIS worker
thread running C1.
After modifying Machine.Config such that the "ProcessModel" tag used the
"system" account instead of the "machine" account, I was able to get this
working in Debug mode. The modification was required to enable transition #2
(listed above). Prior to making this modification an exception was thrown
indicating an inability to call COM+ class C2. (Sorry, I don't recall the
exact exception.)

When I say Debug mode, I'm referring to running the code within the
VS.NET and VS6 IDEs and stepping between break points.

With everything working in Debug mode, I then attempted to execute the code
without debugging. Based on well placed App.LogEvent and EventLog.WriteEntry
calls, it appears that the following is occurring:
All calls prior to the calling of COM+ Class C3 appear to be working.
The Call to COM+ Class C3 doesn't raise a COM+ error, but the variant
returned from this call is empty. During successful execution the resulting
variant contains an array with a "UBound" of 5. The real puzzling thing
about this situation is that an error with COM+ class C3 should result in a
variant containing an array with a "UBound" of 3. There should always be an
array returned from COM+ C3!
So the questions are as follows:
Is it possible that the return values, (which are passed ByRef), aren't
being marshalled properly between COM+ Class C2 and COM+ Class C3?
Is it possible that the call from COM+ Class C2 to COM+ Class C3 is failing
silently? (Placing App.LogEvent calls within COM+ Class C3 requires the
involvement of another team.)
Is there some security or thread related issue here that I'm just not
seeing? And does this underlying issue explain why things work during Debug
and fail when not running under an IDE managed thread?
Thanks for taking the time to read all of that. :)
 
D

Duane Pressley

Thanks for the reply Nicholas.

To clarify things a bit:
1.. There are 2 .NET classes in my scenario, and neither of these are derived from ServicedComponent.
2.. The COM+ classes involved, (C1, C2, and C3), are all members of the same COM+ application.
Are you suggesting that I should move one of my .NET classes into COM+?

In an attempt to explore your thoughts that this may be related to the COM apartment of the ThreadPool thread, I did the following:
1.. Marked the N2 method, (this is the method run on the ThreadPool thread), with the [STAThread] attribute. This produced the same results.
2.. Used the Thread.CurrentThread.ApartmentState property to set the ApartmentState to STA. Again same results as before.
Thanks for the post...any other ideas?
Nicholas Paldino said:
Duane,

I believe that there is a threading issue here that could be
contributing to some of the issues you are seeing. The threads in the
ThreadPool class do not belong to any COM compartment by default. This is a
big issue, because components that derive from ServicedComponent are not
free-threaded. From the section of the .NET framework documentation titled
"Managed and Unmanaged Threading in Microsoft Windows":

Managed objects that are exposed to COM behave as if they had aggregated the
free-threaded marshaler. In other words, they can be called from any COM
apartment in a free-threaded manner. The only managed objects that do not
exhibit this free-threaded behavior are those objects that derive from
ServicedComponent.

Since you declared that your components are COM+ components, I'm
assuming they are all derived from ServicedComponent.

Because the apartment is not set up correctly, you probably are not
getting the correct context for your components, which can result in a
number of the issues that you are seeing.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- casper(1 spelled out){at)caspers(where I live, rhymes with
mouse)<dot]com

I'm looking for someone to help me make sense of the results I'm observing
when using the ThreadPool class in a COM-Interop scenario. Here's the set
up:
A classic ASP page instantiates and calls MethodA on COM+ Class (C1).
MethodA of COM+ class (C1) instantiates and calls MethodB of .NET class
(N1). (Note: N1 has been registered using RegASM and is present in the GAC).
MethodB of .NET class (N1) uses the ThreadPool.QueueUserWorkItem method to
queue up a call to MethodC on .NET Class (N2).
MethodC of .NET Class (N2), (called on a ThreadPool thread), instantiates
and calls MethodD on COM+ class (C2).
MethodD of COM+ Class (C2) instantiates and calls MethodE on COM+ class
(C3).
Finally, methodB of .NET Class (N1) uses static members of .NET Class (N2)
to retrieve the results of the "background" processing. These results are
passed back to COM+ Class (C1) and ultimately displayed on the ASP page.
Note: All COM+ classes are registered within the same COM+ application;
and this application is configured as a "Library" application.

I believe this sequence of calls results in the following transitions:
An IIS worker thread, (running C1), transitions to .NET managed thread,
(running N1). I'm not at all clear as to what process owns the .NET thread.
As a result of item#1 a .NET ThreadPool thread, (running N2), transitions to
a COM+ thread, (running C2).
I'm assuming the same COM+ Thread from item#2 is used to run C3.
The COM+ Thread running C2 and C3 completes and transitions back to the .NET
ThreadPool thread running N2.
Based on a flag exposed as a static member of N2, the "original" .NET Thread
begins accessing static members of N2. (These static members are used to
aggregate results across multiple ThreadPool threads.)
Finally, the "original" .NET thread transitions back to the IIS worker
thread running C1.
After modifying Machine.Config such that the "ProcessModel" tag used the
"system" account instead of the "machine" account, I was able to get this
working in Debug mode. The modification was required to enable transition #2
(listed above). Prior to making this modification an exception was thrown
indicating an inability to call COM+ class C2. (Sorry, I don't recall the
exact exception.)

When I say Debug mode, I'm referring to running the code within the
VS.NET and VS6 IDEs and stepping between break points.

With everything working in Debug mode, I then attempted to execute the code
without debugging. Based on well placed App.LogEvent and EventLog.WriteEntry
calls, it appears that the following is occurring:
All calls prior to the calling of COM+ Class C3 appear to be working.
The Call to COM+ Class C3 doesn't raise a COM+ error, but the variant
returned from this call is empty. During successful execution the resulting
variant contains an array with a "UBound" of 5. The real puzzling thing
about this situation is that an error with COM+ class C3 should result in a
variant containing an array with a "UBound" of 3. There should always be an
array returned from COM+ C3!
So the questions are as follows:
Is it possible that the return values, (which are passed ByRef), aren't
being marshalled properly between COM+ Class C2 and COM+ Class C3?
Is it possible that the call from COM+ Class C2 to COM+ Class C3 is failing
silently? (Placing App.LogEvent calls within COM+ Class C3 requires the
involvement of another team.)
Is there some security or thread related issue here that I'm just not
seeing? And does this underlying issue explain why things work during Debug
and fail when not running under an IDE managed thread?
Thanks for taking the time to read all of that. :)
 
D

Duane Pressley

After further review, it appears that my problem was due to an apparent inability to call an in-process STA COM+ Class from a MTA "ThreadPool" thread.

Moving COM+ Class (C2) to an out-of-process "Server" application allowed me to "work-around" my initial issue.

Does anyone know if it is possible to successfully call an in-process STA COM+ Class from a "ThreadPool" thread?


Thanks for the reply Nicholas.

To clarify things a bit:
1.. There are 2 .NET classes in my scenario, and neither of these are derived from ServicedComponent.
2.. The COM+ classes involved, (C1, C2, and C3), are all members of the same COM+ application.
Are you suggesting that I should move one of my .NET classes into COM+?

In an attempt to explore your thoughts that this may be related to the COM apartment of the ThreadPool thread, I did the following:
1.. Marked the N2 method, (this is the method run on the ThreadPool thread), with the [STAThread] attribute. This produced the same results.
2.. Used the Thread.CurrentThread.ApartmentState property to set the ApartmentState to STA. Again same results as before.
Thanks for the post...any other ideas?
Nicholas Paldino said:
Duane,

I believe that there is a threading issue here that could be
contributing to some of the issues you are seeing. The threads in the
ThreadPool class do not belong to any COM compartment by default. This is a
big issue, because components that derive from ServicedComponent are not
free-threaded. From the section of the .NET framework documentation titled
"Managed and Unmanaged Threading in Microsoft Windows":

Managed objects that are exposed to COM behave as if they had aggregated the
free-threaded marshaler. In other words, they can be called from any COM
apartment in a free-threaded manner. The only managed objects that do not
exhibit this free-threaded behavior are those objects that derive from
ServicedComponent.

Since you declared that your components are COM+ components, I'm
assuming they are all derived from ServicedComponent.

Because the apartment is not set up correctly, you probably are not
getting the correct context for your components, which can result in a
number of the issues that you are seeing.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- casper(1 spelled out){at)caspers(where I live, rhymes with
mouse)<dot]com

I'm looking for someone to help me make sense of the results I'm observing
when using the ThreadPool class in a COM-Interop scenario. Here's the set
up:
A classic ASP page instantiates and calls MethodA on COM+ Class (C1).
MethodA of COM+ class (C1) instantiates and calls MethodB of .NET class
(N1). (Note: N1 has been registered using RegASM and is present in the GAC).
MethodB of .NET class (N1) uses the ThreadPool.QueueUserWorkItem method to
queue up a call to MethodC on .NET Class (N2).
MethodC of .NET Class (N2), (called on a ThreadPool thread), instantiates
and calls MethodD on COM+ class (C2).
MethodD of COM+ Class (C2) instantiates and calls MethodE on COM+ class
(C3).
Finally, methodB of .NET Class (N1) uses static members of .NET Class (N2)
to retrieve the results of the "background" processing. These results are
passed back to COM+ Class (C1) and ultimately displayed on the ASP page.
Note: All COM+ classes are registered within the same COM+ application;
and this application is configured as a "Library" application.

I believe this sequence of calls results in the following transitions:
An IIS worker thread, (running C1), transitions to .NET managed thread,
(running N1). I'm not at all clear as to what process owns the .NET thread.
As a result of item#1 a .NET ThreadPool thread, (running N2), transitions to
a COM+ thread, (running C2).
I'm assuming the same COM+ Thread from item#2 is used to run C3.
The COM+ Thread running C2 and C3 completes and transitions back to the .NET
ThreadPool thread running N2.
Based on a flag exposed as a static member of N2, the "original" ..NET Thread
begins accessing static members of N2. (These static members are used to
aggregate results across multiple ThreadPool threads.)
Finally, the "original" .NET thread transitions back to the IIS worker
thread running C1.
After modifying Machine.Config such that the "ProcessModel" tag used the
"system" account instead of the "machine" account, I was able to get this
working in Debug mode. The modification was required to enable transition #2
(listed above). Prior to making this modification an exception was thrown
indicating an inability to call COM+ class C2. (Sorry, I don't recall the
exact exception.)

When I say Debug mode, I'm referring to running the code within the
VS.NET and VS6 IDEs and stepping between break points.

With everything working in Debug mode, I then attempted to execute the code
without debugging. Based on well placed App.LogEvent and EventLog.WriteEntry
calls, it appears that the following is occurring:
All calls prior to the calling of COM+ Class C3 appear to be working.
The Call to COM+ Class C3 doesn't raise a COM+ error, but the variant
returned from this call is empty. During successful execution the resulting
variant contains an array with a "UBound" of 5. The real puzzling thing
about this situation is that an error with COM+ class C3 should result in a
variant containing an array with a "UBound" of 3. There should always be an
array returned from COM+ C3!
So the questions are as follows:
Is it possible that the return values, (which are passed ByRef), aren't
being marshalled properly between COM+ Class C2 and COM+ Class C3?
Is it possible that the call from COM+ Class C2 to COM+ Class C3 is failing
silently? (Placing App.LogEvent calls within COM+ Class C3 requires the
involvement of another team.)
Is there some security or thread related issue here that I'm just not
seeing? And does this underlying issue explain why things work during Debug
and fail when not running under an IDE managed thread?
Thanks for taking the time to read all of that. :)
 
M

Mr.Tickle

If i use the threadpool for like 3.. to 5 threads , is there a gurantee that they will be started pretty close to when i requested them? or what would make them wait somehow, is there a way to determine that after a period of time that a thread pooled hasnt started then i can abort it and do a new thread start?


After further review, it appears that my problem was due to an apparent inability to call an in-process STA COM+ Class from a MTA "ThreadPool" thread.

Moving COM+ Class (C2) to an out-of-process "Server" application allowed me to "work-around" my initial issue.

Does anyone know if it is possible to successfully call an in-process STA COM+ Class from a "ThreadPool" thread?


Thanks for the reply Nicholas.

To clarify things a bit:
1.. There are 2 .NET classes in my scenario, and neither of these are derived from ServicedComponent.
2.. The COM+ classes involved, (C1, C2, and C3), are all members of the same COM+ application.
Are you suggesting that I should move one of my .NET classes into COM+?

In an attempt to explore your thoughts that this may be related to the COM apartment of the ThreadPool thread, I did the following:
1.. Marked the N2 method, (this is the method run on the ThreadPool thread), with the [STAThread] attribute. This produced the same results.
2.. Used the Thread.CurrentThread.ApartmentState property to set the ApartmentState to STA. Again same results as before.
Thanks for the post...any other ideas?
Nicholas Paldino said:
Duane,

I believe that there is a threading issue here that could be
contributing to some of the issues you are seeing. The threads in the
ThreadPool class do not belong to any COM compartment by default. This is a
big issue, because components that derive from ServicedComponent are not
free-threaded. From the section of the .NET framework documentation titled
"Managed and Unmanaged Threading in Microsoft Windows":

Managed objects that are exposed to COM behave as if they had aggregated the
free-threaded marshaler. In other words, they can be called from any COM
apartment in a free-threaded manner. The only managed objects that do not
exhibit this free-threaded behavior are those objects that derive from
ServicedComponent.

Since you declared that your components are COM+ components, I'm
assuming they are all derived from ServicedComponent.

Because the apartment is not set up correctly, you probably are not
getting the correct context for your components, which can result in a
number of the issues that you are seeing.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- casper(1 spelled out){at)caspers(where I live, rhymes with
mouse)<dot]com

I'm looking for someone to help me make sense of the results I'm observing
when using the ThreadPool class in a COM-Interop scenario. Here's the set
up:
A classic ASP page instantiates and calls MethodA on COM+ Class (C1).
MethodA of COM+ class (C1) instantiates and calls MethodB of .NET class
(N1). (Note: N1 has been registered using RegASM and is present in the GAC).
MethodB of .NET class (N1) uses the ThreadPool.QueueUserWorkItem method to
queue up a call to MethodC on .NET Class (N2).
MethodC of .NET Class (N2), (called on a ThreadPool thread), instantiates
and calls MethodD on COM+ class (C2).
MethodD of COM+ Class (C2) instantiates and calls MethodE on COM+ class
(C3).
Finally, methodB of .NET Class (N1) uses static members of .NET Class (N2)
to retrieve the results of the "background" processing. These results are
passed back to COM+ Class (C1) and ultimately displayed on the ASP page.
Note: All COM+ classes are registered within the same COM+ application;
and this application is configured as a "Library" application.

I believe this sequence of calls results in the following transitions:
An IIS worker thread, (running C1), transitions to .NET managed thread,
(running N1). I'm not at all clear as to what process owns the ..NET thread.
As a result of item#1 a .NET ThreadPool thread, (running N2), transitions to
a COM+ thread, (running C2).
I'm assuming the same COM+ Thread from item#2 is used to run C3.
The COM+ Thread running C2 and C3 completes and transitions back to the .NET
ThreadPool thread running N2.
Based on a flag exposed as a static member of N2, the "original" ..NET Thread
begins accessing static members of N2. (These static members are used to
aggregate results across multiple ThreadPool threads.)
Finally, the "original" .NET thread transitions back to the IIS worker
thread running C1.
After modifying Machine.Config such that the "ProcessModel" tag used the
"system" account instead of the "machine" account, I was able to get this
working in Debug mode. The modification was required to enable transition #2
(listed above). Prior to making this modification an exception was thrown
indicating an inability to call COM+ class C2. (Sorry, I don't recall the
exact exception.)

When I say Debug mode, I'm referring to running the code within the
VS.NET and VS6 IDEs and stepping between break points.

With everything working in Debug mode, I then attempted to execute the code
without debugging. Based on well placed App.LogEvent and EventLog.WriteEntry
calls, it appears that the following is occurring:
All calls prior to the calling of COM+ Class C3 appear to be working.
The Call to COM+ Class C3 doesn't raise a COM+ error, but the variant
returned from this call is empty. During successful execution the resulting
variant contains an array with a "UBound" of 5. The real puzzling thing
about this situation is that an error with COM+ class C3 should result in a
variant containing an array with a "UBound" of 3. There should always be an
array returned from COM+ C3!
So the questions are as follows:
Is it possible that the return values, (which are passed ByRef), aren't
being marshalled properly between COM+ Class C2 and COM+ Class C3?
Is it possible that the call from COM+ Class C2 to COM+ Class C3 is failing
silently? (Placing App.LogEvent calls within COM+ Class C3 requires the
involvement of another team.)
Is there some security or thread related issue here that I'm just not
seeing? And does this underlying issue explain why things work during Debug
and fail when not running under an IDE managed thread?
Thanks for taking the time to read all of that. :)
 
D

Duane Pressley

My experiences so far suggest that you are unable to "predict" when the ThreadPool threads will be started. The the ThreadPool process appears to start the "background" threads based on CPU availability.

Keep in mind, there is no way to "cancel" a "work item" that has been queued using the ThreadPool.QueueUserWorkItem method. You may need to manage your own pool of threads which would allow to have complete control over the starting, stopping, and aborting of those threads.

Hope that helps.
If i use the threadpool for like 3.. to 5 threads , is there a gurantee that they will be started pretty close to when i requested them? or what would make them wait somehow, is there a way to determine that after a period of time that a thread pooled hasnt started then i can abort it and do a new thread start?


After further review, it appears that my problem was due to an apparent inability to call an in-process STA COM+ Class from a MTA "ThreadPool" thread.

Moving COM+ Class (C2) to an out-of-process "Server" application allowed me to "work-around" my initial issue.

Does anyone know if it is possible to successfully call an in-process STA COM+ Class from a "ThreadPool" thread?


Thanks for the reply Nicholas.

To clarify things a bit:
1.. There are 2 .NET classes in my scenario, and neither of these are derived from ServicedComponent.
2.. The COM+ classes involved, (C1, C2, and C3), are all members of the same COM+ application.
Are you suggesting that I should move one of my .NET classes into COM+?

In an attempt to explore your thoughts that this may be related to the COM apartment of the ThreadPool thread, I did the following:
1.. Marked the N2 method, (this is the method run on the ThreadPool thread), with the [STAThread] attribute. This produced the same results.
2.. Used the Thread.CurrentThread.ApartmentState property to set the ApartmentState to STA. Again same results as before.
Thanks for the post...any other ideas?
Nicholas Paldino said:
Duane,

I believe that there is a threading issue here that could be
contributing to some of the issues you are seeing. The threads in the
ThreadPool class do not belong to any COM compartment by default. This is a
big issue, because components that derive from ServicedComponent are not
free-threaded. From the section of the .NET framework documentation titled
"Managed and Unmanaged Threading in Microsoft Windows":

Managed objects that are exposed to COM behave as if they had aggregated the
free-threaded marshaler. In other words, they can be called from any COM
apartment in a free-threaded manner. The only managed objects that do not
exhibit this free-threaded behavior are those objects that derive from
ServicedComponent.

Since you declared that your components are COM+ components, I'm
assuming they are all derived from ServicedComponent.

Because the apartment is not set up correctly, you probably are not
getting the correct context for your components, which can result in a
number of the issues that you are seeing.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- casper(1 spelled out){at)caspers(where I live, rhymes with
mouse)<dot]com

I'm looking for someone to help me make sense of the results I'm observing
when using the ThreadPool class in a COM-Interop scenario. Here's the set
up:
A classic ASP page instantiates and calls MethodA on COM+ Class (C1).
MethodA of COM+ class (C1) instantiates and calls MethodB of ..NET class
(N1). (Note: N1 has been registered using RegASM and is present in the GAC).
MethodB of .NET class (N1) uses the ThreadPool.QueueUserWorkItem method to
queue up a call to MethodC on .NET Class (N2).
MethodC of .NET Class (N2), (called on a ThreadPool thread), instantiates
and calls MethodD on COM+ class (C2).
MethodD of COM+ Class (C2) instantiates and calls MethodE on COM+ class
(C3).
Finally, methodB of .NET Class (N1) uses static members of .NET Class (N2)
to retrieve the results of the "background" processing. These results are
passed back to COM+ Class (C1) and ultimately displayed on the ASP page.
Note: All COM+ classes are registered within the same COM+ application;
and this application is configured as a "Library" application.

I believe this sequence of calls results in the following transitions:
An IIS worker thread, (running C1), transitions to .NET managed thread,
(running N1). I'm not at all clear as to what process owns the ..NET thread.
As a result of item#1 a .NET ThreadPool thread, (running N2), transitions to
a COM+ thread, (running C2).
I'm assuming the same COM+ Thread from item#2 is used to run C3.
The COM+ Thread running C2 and C3 completes and transitions back to the .NET
ThreadPool thread running N2.
Based on a flag exposed as a static member of N2, the "original" ..NET Thread
begins accessing static members of N2. (These static members are used to
aggregate results across multiple ThreadPool threads.)
Finally, the "original" .NET thread transitions back to the IIS worker
thread running C1.
After modifying Machine.Config such that the "ProcessModel" tag used the
"system" account instead of the "machine" account, I was able to get this
working in Debug mode. The modification was required to enable transition #2
(listed above). Prior to making this modification an exception was thrown
indicating an inability to call COM+ class C2. (Sorry, I don't recall the
exact exception.)

When I say Debug mode, I'm referring to running the code within the
VS.NET and VS6 IDEs and stepping between break points.

With everything working in Debug mode, I then attempted to execute the code
without debugging. Based on well placed App.LogEvent and EventLog.WriteEntry
calls, it appears that the following is occurring:
All calls prior to the calling of COM+ Class C3 appear to be working.
The Call to COM+ Class C3 doesn't raise a COM+ error, but the variant
returned from this call is empty. During successful execution the resulting
variant contains an array with a "UBound" of 5. The real puzzling thing
about this situation is that an error with COM+ class C3 should result in a
variant containing an array with a "UBound" of 3. There should always be an
array returned from COM+ C3!
So the questions are as follows:
Is it possible that the return values, (which are passed ByRef), aren't
being marshalled properly between COM+ Class C2 and COM+ Class C3?
Is it possible that the call from COM+ Class C2 to COM+ Class C3 is failing
silently? (Placing App.LogEvent calls within COM+ Class C3 requires the
involvement of another team.)
Is there some security or thread related issue here that I'm just not
seeing? And does this underlying issue explain why things work during Debug
and fail when not running under an IDE managed thread?
Thanks for taking the time to read all of that. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top