views:

223

answers:

5

I am making a C# DLL plugin for a EXE written in VB6. I do not have access to the source of the EXE. The DLL itself works and communicates fine with the EXE.

Here is the process for a event:

  1. User issues command on EXE which then calls a function in the DLL, passing an object as a parameter
  2. DLL processes data which sometimes takes a long time
  3. The DLL responds by calling a function of the object that was passed. The DLL function itself does not return anything

    public void DoCommand(object CommandSettings)
    {
        //ObjectVB6 is my custom class to allow easy calling of COM methods and properties
        ObjectVB6 CS = new ObjectVB6(CommandSettings);
        ... //process data
        CS.CallMethod("MyReply", args);
    }
    

My problem is that during long queries (from the DLL), the EXE's UI freezes.

What is the best way to prevent this? I have tried using asynchronous MySQL queries, which were no good, and tried using multiple threads, which just run into protected memory issues.

Any advice you can provide would be awesome. Been trying to address this issue for days. Thanks.

A: 

Why can't you just use a worker thread for that code? What "protected memory issues" are you running into?

Blindy
A: 

IMO the best way to deal with this is to throw your request into the ThreadPool on the DLL side, "fire and forget" style. Have you tried this?

Otherwise you'll have to jigger up a callback function to your VB6 program to get status, which, as you may have already found out, is tricky due to VB6's Single-Threaded Apartment model.

If you want to explore the perils and rewards of multi-threading in VB6 in greater depth, have a look at the following article. It may allow you do simply start up a thread and do it on the VB6 side:

Multi-Threading In VB5 and VB6
http://www.freevbcode.com/ShowCode.Asp?ID=1287

Robert Harvey
If you want to solve it in VB6, I would try creating an ActiveX exe to wrap the DLL instead. Like the Microsoft coffee sample http://msdn.microsoft.com/en-us/library/aa445814(VS.60).aspx
MarkJ
A: 

All functions developed in .NET can be called asynchronously using a delegate and then calling BeginInvoke to actually call the function. Since your function does not return anything, you won't need to call EndInvoke. By making use of IAsyncResult you can meet your Callback requirement. A good reference for how to do this properly is "Programming .NET Components" by Juval Lowy published by O'Reilly. The ISBN is 0596102070. Good Luck.

EWM2
A: 

I've figured a way to accomplish what I was after. While I would prefer a nicer method, this way works.

Used two queues to share information. Main thread listens to get _get queue, and sets the _set queue when a request is made. Worker thread simple inserts request into _get queue, and waits until _set is ready. The main thread is just acting like a proxy.

Thanks for your help!

Lynxy
Did you try using BackgroundWorker? What you've done sounds like a reimplementation of BackgroundWorker. Try AngryHacker's answer http://stackoverflow.com/questions/1805514/c-best-approach-for-a-responsive-ui-during-sql-query-using-com-interop/1806825#1806825
MarkJ
+1  A: 

Try the following:

BackgroundWorker bw = null; 
ObjectVB6 CS = null;

public void DoCommand(object CommandSettings)
{
    //ObjectVB6 is my custom class to allow easy calling of COM methods and properties
    CS = new ObjectVB6(CommandSettings);

    // hook up background worker
    bw = new BackgroundWorker();
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}

private void bw_DoWork(...)
{
    // process data, e.g. the piece that takes too long
}

private void bw_RunWorkerCompleted
{
   CS.CallMethod("MyReply", args);
}

Like one of the responders said, this may or may not work due to the nature of VB6 apartment threading.

AngryHacker
+1 I think this should work. The whole point of the BackgroundWorker is that the RunWorkerCompleted event occurs on the original thread, so shouldn't have any problems with VB6 apartment threading?
MarkJ
@MarkJ I've had mixed success with this approach. It works in most situations, but not in others. For instance, I've tried to integrate Asterisk.NET into a VB6 project and all I got was 2 weeks of headaches and out of the blue crashes.
AngryHacker