Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call VB6 DLL from a multithreaded c# windows service application?

I'm running a multithreaded windows service that need to call a VB6 dll. There's no documentation about this VB6 dll and this legacy system supports a very critical business process.

At first time (1st thread), this dll performs well. As other threads need access, it start provide wrong results.

I read one guys saying:

"Just be careful of one thing if you are using VB6. Your threading model is going to have to change to support apartments if you are running a multithreaded service. VB only supports multiple single-threaded apartments, but .NET runs fully free threaded normally. The thread that calls into the VB6 DLL needs to be compatible with the DLL."

Another guy from team gave me the idea to put this ddl in a separated application domain. But I'm not sure.

How can we work with VB6 dll called from a multithreaded c# windows service application?

like image 948
Eduardo Xavier Avatar asked Jul 03 '09 20:07

Eduardo Xavier


2 Answers

When the threads come in, are you saving objects and reusing them later on new threads? If you can, create the objects fresh for every thread. We have a situation like this with a data layer dll we use. If you create a connection on one thread, it can't be used from another. If you create a new connection on each thread, it works fine.

If it's slow to create your objects, look at the ThreadPool class and the ThreadStatic attribute. Threadpools recycle the same set of threads over and over to do work, and ThreadStatic lets you create an object that exists for one thread only. eg

[ThreadStatic]
public static LegacyComObject myObject;

As a request comes in, turn it into a job and queue it in your thread pool. When the job starts, check if the static object is initialised;

void DoWork()
{ 
    if (myObject == null)
    { 
        // slow intialisation process
        myObject = New ...
    }

    // now do the work against myObject
    myObject.DoGreatStuff();
}
like image 136
Steve Cooper Avatar answered Sep 20 '22 08:09

Steve Cooper


You say

I'm running a multithreaded windows service that need to call a VB6 dll. There's no documentation about this VB6 dll and this legacy system supports a very critical business process.

and at the same time you say

At first time (1º thread), this dll performs well. As other threads need access, it start provide wrong results.

I'd make very certain that Management is aware of the failure you're seeing because the code supporting the critical business process is old and undocumented, and is being used in a way it was never intended to be used, and was never tested to be used. I bet it's also never been tested to be used from .NET before, has it?

Here's my suggestion, and this is similar to something I've actually implemented:

The VB6 DLL expects to be called on a single thread. Do not disappoint it! When your service starts, have it start up a thread of the appropriate type (I can't say, since I've deliberately forgotten all that STA/MTA stuff). Queue up requests to that thread for access to the VB6 DLL. Have all such access go through the single thread.

That way, as far as the VB6 DLL is concerned, it's running exactly as it was tested to run.


BTW, this is slightly different from what I've implemented. I had a web service, not a Windows Service. I had a C DLL, not VB6, and it wasn't COM. I just refactored all access to the thing into a single class, then put lock statements around each of the public methods.

like image 31
John Saunders Avatar answered Sep 20 '22 08:09

John Saunders