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.![Smile :-) :-)](/styles/default/custom/smilies/smile.gif)
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.
![Smile :-) :-)](/styles/default/custom/smilies/smile.gif)