How to ensure that the same thread is used to execute code in IIS? - vb.net

We have a third party dll that is used in our web service hosted in IIS6. The problem is that once this dll is loaded into memory, the exception AccessViolationException gets thrown if a thread different then the one that created it tries to execute any code within the dll. The worker process is multi threaded and each call to the web service will get a random thread from the pool. We tried to unload it from memory and reload it each time we needed it, but I guess only the front end is .Net and the rest is unmanaged so it never actually gets completely unloaded from memory. We are using VB and .Net 2.0. Any suggestions?
(Response to Rob Walker)
We thought about creating a new thread and using it to call the dll, but how do we make the thread sit and wait for calls? How do you delegate the call to the thread without having the Dispatcher class supplied by .Net 3.0? Creating a hidden form and putting it in a message loop might work. And then we could call the Invoke() method of the form. But I can see many problems occurring if we create a form inside an IIS hosted web service.

I have read about a class in .net 3.0 called Dispatcher that allows you to put a thread in a loop and then call the method Invoke() using a delegate to execute a method using the thread. But this solution will not work if you cannot update to .Net 3.0. Another solution would be to host the third party dll in another application on the server and use some form of Remoting to access it. But you may still have a problem with the Remoting because it behaves similar to IIS and will also pick a random thread to execute the code . To get around this, you could put a wrapper around the dll and use it to delegate the calls to the UI thread by using the Invoke() method of the form.

I think you need to look at using a wrapper thread that handles all calls to the DLL, and deals with the serialization.
This thread is outside of the managed thread pool, so you control its lifetime. But even this would not be foolproof unless you can prevent IIS from restarting the app domain your web service is in.
You also need to worry about what happens when two web service requests come in at the same time. Is each call into the DLL standalone, or do you have to group together all the calls associated with a single web service request before allowing any other request to be serviced?

You could create a service that hosts the extra DLL. Via remoting you access the service, this will dispatch the calls the the thread that manages the DLL.
This way you have control over the thread that calls the DLL, and over the lifetime of the thread.

I'm a bit rusty, but you might try wrapping calls to the DLL in a single threaded apartment COM object. This would ensure that all calls go through the COM object's windows messaging thread. I think you would have to register the component in a server application within Component Services to do this.

Can you run the dll inside different threads as different instances? Like thread1 creates an instance of this third party dll, and thread2 also does, but as long as thread1 doesn't try to use thread2's instance it won't throw that exception? If thats the case, .Net never unloads any code once its loaded, if you load an assembly and then remove it, it still sits in that application pool. If you can create more than one instance at a time, you could load it up in a separate app pool you control per a request, then unload the app pool. Performance might drop though.

Related

Re-issuing COM call on the UI thread

I am trying to decipher the paragraph below, taken from a blog post here which describes COM history in the context of the development for the Visual Studio IDE:
When everything was C++ native code, COM ensured that almost
everything happened on the main STA thread (i.e. the UI thread). If
code running in another apartment (e.g. a background thread) called
any of these COM components the background thread would block while
the call was re-issued on the main thread. This protected the COM
component from having to deal with concurrent execution, but left it
open to reentrancy (being invoked while in an outbound call). This
technique worked whether the caller was managed (automatically) or
native code (via the proxy stub that COM would generate for the
caller).
The questions I have:
What is the mechanism by which a call is re-issued on another thread? Can you give an example?
Is the problem mentioned as ‘concurrent execution’ the same as that of thread safety?
What is being invoked while on an outbound call?
Thank you.

WCF Client CloseAsync vs Abort()

I'm using Portable Class Libraries to build service classes that all our UI technology with use to communicate with our services.
These libraries will support Silverlight, Asp.Net and any other .Net UI technology.
Since Silverlight is supported, all calls must be asynchronous.
With Silverlight, I can call CloseAsync() immediately after client.Method() call to the service.
However, I'm finding that doesn't work with Asp.Net clients.
I don't want to use CloseAync() in the completed code because if multiple async calls are being made you could run into a timing issue.
I'd rather not have to come up with a lot of logic something like putting a while loop in every async method to make sure CloseAsync() hasn't been called and completed.
Right now I'm testing just using Abort in the completed sections and everything appears to be working fine.
Just curious if anybody else out there knows of any problems we may run into Using Abort?
Thanks.
We're using .Net 4.5.
It depends on which binding you're using. If you're using a binding which uses sessions, then calling Close[Async] will attempt to first close that session (e.g., WSHttpBinding with reliable messaging), then close the connection, otherwise it will remain alive in the server side until it times out. If you're using a binding which does not use sessions (i.e., BasicHttpBinding), then they're pretty much equivalent.

Best practice for calling an STA Visual Basic 6.0 COM object in a WCF service: Concurrent access

I have a WCF service which calls an STA Visual Basic 6.0 COM object. Everything works normally if only one client is using the service, but as soon as concurrent users start to call it, I'm in trouble and getting all kinds of random errors when calling one of the methods of the COM object.
At first I fixed this problem by adding support for the STAOperationBehavior attribute with the help of the article Calling an STA COM Object from a WCF Operation.
Well, it helped a lot and for some time everything seemed to work well, but now I started to get System.AccessViolationException errors on a particular server when more than one user is calling the service.
I've read that this is probably a thread problem, and I should use mutex or instancecontext in my web service.
What is the best practice for making sure that concurrent users can use an STA COM object in a WCF service without any problems?
If the object is not designed to be used simultaneously by multiple users, then you simply cannot allow multiple users to use it.

How are STA COM components handled when used in a WCF service hosted in IIS (7+)?

From what I understand, when a COM component marked as using STA is used from an MTA thread, the calls are supposed to be marshalled to an STA thread and executed from that dedicated thread. In the case of a Windows client application, this would mean that it would execute on the UI thread (if marked as STA), and that callbacks from the COM component to me would be handled by Windows messages sent to a hidden window and processed on the Windows message loop.
What happens though if I use a STA COM component in a WCF service hosted in IIS? Will the worker process have a Windows message loop on a STA thread? Can I fire up my own STA thread with its own message loop?
The COM runtime looks after the dispatching of calls to methods on a COM object inside an STA: you are right that this is based on the same OS mechanism used for dispatching Windows messages, but you don't need to worry about making this happen - COM does this for you under the hood.
What you do need to worry about is which STA your COM objects are going to live in. If you instantiate apartment-threaded COM objects using COM Interop from a WCF service, you need to be careful.
If the thread on which you do this is not an STA thread, then all in-process COM objects will live in the default Host STA for the IIS worker process. You do not want this to happen: all your COM objects for all service operations will end up in this same STA. The clue is in the name - there is just one thread for all the objects - and all calls to their methods will be serialized waiting for the one and only thread in the apartment to execute them. Your service will not scale to handle multiple concurrent clients.
You need to make sure that COM objects you instantiate to service a particular WCF request are in their own STA separate from objects created for other requests. There are broadly two ways to do this:
Spin up your own Thread, specifying ApartmentState.STA in SetApartmentState() before you start it, on which to instantiate the COM objects for a particular request. This is the approach detailed by Scott Seely in the link in Kev's answer: he ensures that each service operation call is invoked on a new STA-initialised Thread. A harder but more scalable solution along these lines would be to implement a pool of reusable STA-initialised Threads.
Host your COM objects in a COM+ Application, so that they live in a separate DllHost process, where COM+ (through its abstraction called the Activity) can take care of putting the objects for different requests into different STAs.
I'm not sure exactly what you mean when you refer to callbacks. Perhaps you mean COM method calls on some COM interface implemented in your managed code, via a reference passed in to the COM objects as an argument to one of the COM objects' methods: if so, this should just work. But perhaps you mean something else, in which case perhaps you could amend the question to clarify.
I've found that you need to pump messages on your STA thread in a WCF service or you miss callbacks from the COM object.
The following code works, but it requires you call the COM object via a Dispatcher.
ComWrapper comWrapper;
Thread localThread;
Dispatcher localThreadDispatcher;
public Constructor()
{
localThread = new Thread(ThreadProc)
{
Name = "test"
};
localThread.SetApartmentState(ApartmentState.STA);
AutoResetEvent init = new AutoResetEvent(false);
localThread.Start(init);
init.WaitOne();
}
private void ThreadProc(object o)
{
localThreadDispatcher = Dispatcher.CurrentDispatcher;
((AutoResetEvent)o).Set();
comWrapper = new ComWrapper()
Dispatcher.Run();
localThreadFinished.Set();
}
And then make calls as follows.
public void UsefulComOperation()
{
localThreadDispatcher.Invoke(new Action( () => comWrapper.UsefulOperation);
}

Initial Event in Windows Console

I'm creating a Windows Console application written in VB.NET and I have a few processes that need to be called only once during the lifetime of the application. If it was an ASP.NET application, I put these in the Appliction_Start method of the Global.asax.vb file. Since there isn't a Global.asax.vb for Console applications, is there an event I could handle that allows me to call my functions before Main is called?
Is there a problem with just calling them first in main?
Main is the first method where you can grab the needed information / inizialize global stuff.
Why would you need an earlier point? The only thing that is different to Application_Start is that no other method is called automatically (unlike in a web application where the site is opened and the code executed).