tags:

views:

616

answers:

3

I have a VB6 app that processes for a very, very long time. Killing it directly is not feasible, so I would like to set some sort of flag in the VB6 app. If in my C# app I decide to shut it down, I would like to toggle this flag to let the VB6 app know that a shutdown has been requested. Now, I also need something that is named because there will be several of the VB6 apps spun up as activex exes. Does anyone have any idea how to implement something like this? The workflow follows below

C# app - Spin up mulitple VB6 activex.exes in separate threads, Initialize the app with something (henceforth called a flag) I can change in C#, and call the DoStuff command, which takes a very long time to return.

VB6 - Gets the initialize command with the flag. DoStuff gets called. In the DoStuff loop, it checks if the flag is still set.

C# - Kill the project by setting the flag to another state

Any ideas?

+1  A: 

When you create the ActiveX Object keep a reference stored in the application or the thread. COM will handle the marshaling across threads. With a reference in hand you can call a method on it and kill it. If you keep the reference in the thread then you will need to use the interprocess messaging mechanism of .NET to pass to the .NET thread that you want to set the kill flag on the ActiveX EXE.

RS Conley
The VB6 app is blocking unfortunately(since its single threaded), so I need some way of signaling it that it should stop the calculation its in the middle of
Steve
I thought you were spawning the Active EXes in a .NET thread?
RS Conley
I think he means the VB6 app won't process the ActiveX calls, because it's busy. He could pass a reference to an object into the VB6 from the C#, and then have the VB6 poll that object periodically when it's ready to see whether it's time to shut down.
MarkJ
An alternative is to poll by raising events from the VB6 rather than calling back. Both those techniques can make it unecessary to multithread the C# app. The first routine in the Vb6 sets a Timer, then returns immediately to unblock the C#. The Timer_Click event starts the lengthy calculation going
MarkJ
When you say it is blocking, have you tried it? If you are in a loop you'll might need to call DoEvents so the VB6 app can process any queued up messages and COM calls. I'm not sure if COM calls will timeout or not.
Will Rickards
COM calls do time out. 5 seconds by default. As specified in VB6 manual: http://msdn.microsoft.com/en-us/library/aa245850(VS.60).aspx
MarkJ
A: 

I wouldn't keep a reference open across process boundaries but you can certianly cache the Long hWnd of the process and call kill on it from within .Net.

MaSuGaNa
+4  A: 

Here is a pretty standard scheme for asynchronous background processing with VB6 clients and VB6 servers. (For instance it's in Dan Appleman's book and Microsoft's VB6 samples.) I think it should work for a C# client too.

  • The VB6 ActiveX EXE object should expose an event CheckQuitDoStuff(). This takes a ByRef Boolean called Quit.
  • The client calls StartDoStuff in the ActiveX EXE object. This routine starts a Timer on a hidden form and immediately returns. This unblocks the calling thread. The Timer interval is very short so the Timer event fires quickly.
  • The Timer event handler disables the Timer, and then calls back into the ActiveX object DoStuff method. This begins the lengthy processing.
  • Periodically the DoStuff method raises the CheckQuitDoStuff event. The client's event handler checks the special flag and sets Quit True if it's necessary to abort. Then DoStuff aborts the calculation and returns early if Quit is True.

This scheme means that the client doesn't actually need to be multi-threaded, since the calling thread doesn't block while "DoStuff" is happening. The tricky part is making sure that DoStuff raises the events at appropriate intervals - too long, and you can't quit when you want to: too short, and you are slowing down DoStuff unecessarily. Also, when DoStuff exits, it must unload the hidden form.

If DoStuff does actually manage to get all the stuff done before being aborted, you can raise a different event to tell the client that the job is finished.

MarkJ
+1. This is by far the easiest way to get multi-threading for free in VB6 and works well, plus it doesn't risk destabilizing your program or IDE the way that trying to do Win32 threads directly from VB6 code can.
Mike Spross