Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

.NET Web Services and Visual FoxPro COM Object Threading Issues


:P
On this page:

One good reason to use .NET with Visual FoxPro is to publish Web Services. Since the SOAP Toolkit is severely limited in what types of services it can publish using .NET to handle exporting of services is fairly straight forward to do and many developers have surely gone that route.

 

But what you might not be aware of is that there’s a serious issue with Web Services when used with Visual FoxPro in that .NET Web Services run in Multithreaded Apartments (MTA) which means that they are running in a threading model that assumes that all code is multi-threaded. Visual FoxPro COM components however are Single Threaded (STA) and while they will load on MTA their behavior may become erratic if multiple instances are simultaneously executed. Essentially what happens is that in MTA threaded apartments .NET creates one STA thread on which all COM objects are then loaded which means:

 

  • Only one COM object can execute at a time
  • There’s potential for thread leakage as all of them share the same thread
    and the same Thread Local Storage (TLS)

 

Which spells big problems for performance and can easily lead to corruption of data buffers and other global storage that VFP internally uses. In other words it doesn’t work out of the box.

 

I just ran into this with one of my customers who’s running a relatively small application that publishes some summary reports via a Web Service interface and they ended up getting some cross talk where data was getting mixed up between two clients. Ouch.

 

Unlike ASP.NET (ASPX) pages, Web Services in .NET do not have an ASPCOMPAT setting so you can’t easily coerce a Web Service request to be initiated on an STA thread. ASPCOMPAT cause ASP.NET to go through some internal thread management by basically offloading requests to a separate pool of threads made available by COM+ and running the requests of these STA threads instead. Alas, this functionality is not available directly for Web Services.

 

When I was researching this topic I ran into an MSDN article from Jeff Prosise which provides a hacky solution to this problem by creating a custom ASP.NET Handler for ASMX requests and routing it through the ASP.NET Page handler first. The Page handler includes methods to initiate requests on ASPCompat STA threads and his solution basically highjacks the page handler just for this functionality and then manually processes the Web Service request.

 

Here’s the code from handler Jeff’s article and I verified indeed that it works properly with VFP COM components:

 

using System;

using System.Web;

using System.Web.UI;

using System.Web.Services.Protocols;

using System.Web.SessionState;

 

public class AspCompatWebServiceStaHandler :

    System.Web.UI.Page, IHttpAsyncHandler, IRequiresSessionState

{

    protected override void OnInit(EventArgs e)

    {

        IHttpHandler handler =

            new WebServiceHandlerFactory().GetHandler(

                this.Context,

                this.Context.Request.HttpMethod,

                this.Context.Request.FilePath,

                this.Context.Request.PhysicalPath);

        handler.ProcessRequest(this.Context);

        this.Context.ApplicationInstance.CompleteRequest();

    }

 

    public IAsyncResult BeginProcessRequest(

        HttpContext context, AsyncCallback cb, object extraData)

    {               

        return this.AspCompatBeginProcessRequest(

            context, cb, extraData);

    }

 

    public void EndProcessRequest(IAsyncResult result)

    {

        this.AspCompatEndProcessRequest(result);

    }

}

 

You need to add this class to your APP_CODE directory and then register the handler in Web.config:

 

<?xml version="1.0"?>

<configuration>

    <system.web>

      <httpHandlers>

        <add verb="*" path="*.asmx"

          type="AspCompatWebServiceStaHandler" />

      </httpHandlers>

    </system.web>

</configuration>

 

It ain’t pretty but it works. This makes your Visual FoxPro components run properly with ASMX Web Services. It’s a shame there’s not a flag somewhere on the ASMX handler to provide this, but so it goes…

 

Hopes this saves somebody some time…

Posted in ASP.NET  FoxPro  Web Services  

The Voices of Reason


 

Kevin Dente
November 21, 2006

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

I've been complaining about this for ages:
http://weblogs.asp.net/kdente/archive/2003/10/24/33370.aspx

And was very disappointed when it wasn't addressed in 2.0. We'd previously worked around the problem using Microsoft's original suggestion of sourcing the COM components out of a COM+ library application. It works, but Jeff's solution works even better.

Rick Strahl
November 21, 2006

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

Yeah it seems silly that there's not some assembly level attribute available to make this happen more generically.

I just took a look at your post and the link back to the Adapter Pattern. Yuk... Talk about overkill for a simple problem. It's amazing what qualifies as 'pattern' these days.

I didn't actually try a COM+ component, but like you I'm wary to use them unless I really need to. The biggest issue though with COM+ is always performance which is usually considerably worse through COM+ than with raw STA apartments even though you do get better administration for the object.

Kevin Dente
November 21, 2006

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

Since COM+ Library applications are in-proc, the overhead isn't as great as with Server applications - it does perform reasonably. But you still have cross-apartment marshalling, which Jeff's approach handily avoids. We've definitely seen a reduction in CPU utilization after implementing his approach.

Rick Strahl
November 22, 2006

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

Kevin, unfortunately though I found that STA components don't do very well in library projects. We've had lots of lockups with FoxPRo components in the past where out of proc worked much more reliably.

Frankly it's been some time since I had to deal with COM+ and good riddance to that nightmare <s>... But COM issues still pop up here and there and this is important.

I wonder what the issues will be in relation to WCF...

Kevin Dente
November 22, 2006

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

Interesting - with our stuff I experienced the opposite - Library applications worked where Server applications didn't. I assume it varies greatly depending on the COM library.

>good riddance to that nightmare
Amen to that.

John Burrows
May 03, 2010

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

Hi Guys

Just wondering if there is a better solution to this now or is it still an issue?

Thanks
John

Maurice
June 22, 2011

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

I need to has AspCompat true for my asmx and trying this solution, but I keep getting:-
Parser Error Message: Could not load type 'AspCompatWebServiceStaHandler'

When I try appending the , __code it also make no difference.

By the way should the AspCompatWebServiceStaHandler file have the .cs extension? Tried that too.
Any ideas help please?

Dan
April 25, 2012

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

This may be late to the game, but do you need to do this same thing in WCF service application? And can that code be done in VB.NET?

Rick Strahl
April 25, 2012

# re: .NET Web Services and Visual FoxPro COM Object Threading Issues

@Yes something similar needs to be done with WCF, and it's not quite as easy because WCF doesn't run through the ASP.NET framework in the same way that old style Web Services do.

If you can get away with using the old way you should use that. Otherwise you have some work ahead of you.

Here's an article that discusses this (more towards the end):
http://www.netfxharmonics.com/2009/07/Accessing-WPF-Generated-Images-Via-WCF

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024