5
votes

I have some VB6 code I need to slowly move over to .NET. Some of this requires calls to the web. I'm doing the web call from a .NET dll, and when it's done, it fires an event. I handle the event in VB6. Now this works fine on my test machine, and the majority of user's machines, but some users get a consistent crash of the program sometime around when the event is fired.

I'm thinking this is a threading issue. So how should I be handling threads on the .NET side of things? There is no synchronization context when the .NET code is called and I think that might be the issue. How would I get an async operation back to the VB6 calling thread? My VB6 code is STA and I read that things would be marshaled to the VB6 thread through COM automatically, but maybe that was wrong? I don't fully understand what to do if it's indeed a threading issue.

I haven't been able to find a pattern to which computers have the crash issue and which ones don't.

1
Yes, you must raise the event on the thread that called your constructor. You do need a SynchronizationContext, you can easily get one from a Winforms form. One is enough, it doesn't have to be visible, just read its Handle property and it is good to go.Hans Passant
Hmm how would I get that from a VB6 form? I don't open any forms in .NETBen Zuill-Smith
Have you tried separating and comparing .Net frameworks on a possible target machines ? although Microsoft claim full backward compatibility on recent .Net framework versions I found more than once that statement is basically pure horse shit.Stavm
I've compared a working machine to a non-working machine and they both have identical versions of .NET installed, from 2.0 all the way to 4.6.1Ben Zuill-Smith

1 Answers

4
votes

So I found later that I was misinformed and it was not working on pretty much all user's machines except a few developer's machines. The issue was the .tlb file was not being generated and registered.

It seems that if you fire events from the main thread, everything is fine. But if you fire events asynchronously there are only two ways you can make it work without crashing:

  1. You can bring it back to the main thread, perhaps via a SynchronizationContext from a form.
  2. You can fire the event from any thread and let it get marshalled back to VB6's STA thread automatically, BUT it requires extra tlb information that isn't in the registry if you just register the DLL without the tlb option. This option is nice if you don't go through any UI thread that sets a SynchronizationContext.

Note that if you are using reg-free COM, option 2 requires the comInterfaceExternalProxyStub element in your assembly's manifest. See the question and answer here for an example of that