Com Interop Event blocked by WaitOne

I

Iain

I've got a (VC++ 6.0) com object which does something asynchronously (writes
a DVD image, actually).

It rasies COM events to indicate progress, including completion.

I've got this running in a c# application, with the events coming up and
being caught (The idea is to use this to Set a ManualResetEvent which will
alow the rest of the processign to happen).

However, when I put an event after the call to start the async process off,
the events seem never to be caught.

When the WaitOne times out, I get a whole swathe of debug prints from the
COM dll, but the Debug.WriteLine from the (COM) event handler are never
called.

Clearly it's some threading / synchronisation issue, but I've not found
anything obviously relevant in the docs or through google.

Can any one help, please?

Iain
 
D

Dmitriy Lapshin [C# / .NET MVP]

Hi,

As your application is most likely marked with [STAThread], the events
raised by the COM object are handled on the single UI thread your
application has. Once you block the UI thread with WaitOne(), it will never
be able to process further events from the COM object.
 
I

Iain

Thanks Dmitriy.

But what do I DO?

Obviously the com dll is mutlithreaded ('both'). I've been trying to find
something on this attribute in the docs but haven't hit anything I find
particularly useful. Nor with MTAThread which is what I presume I should
use.

The test program is a windows forms program and I've changed the attribute
on Main() to [MTAThread] which has made no difference. I've also changed
the attributes of the methods that seem relevant (and the event handler) in
my class that does all the work - also to no avail.

Lastly, I've replaced the wait with a sleep loop. which I would have
thought would stand some chance of working. but no.

Sorry. still stuck.

Iain
 
I

Iain

I've put a bit of debug code just before the creation of the Com object (and
after the invocation of thee method in the Com object) and the Thread at
those points is MTA.

So it looks like the problem is elsewhere.

The underlying COM object has been coded to work in VB 6 which means that
the events are raised from the main thread (basically the worker thread
sends the event information into a Windows Message loop owned by COM Object.
when this is received it raises the event). So the events are effectively
marshalled on to the initiating thread.

The thread which is doing the writing does not seem visible in the .NET IDE,
however it does continue to operate even after I break the c# stuff.

Iain
Iain said:
Thanks Dmitriy.

But what do I DO?

Obviously the com dll is mutlithreaded ('both'). I've been trying to find
something on this attribute in the docs but haven't hit anything I find
particularly useful. Nor with MTAThread which is what I presume I should
use.

The test program is a windows forms program and I've changed the attribute
on Main() to [MTAThread] which has made no difference. I've also changed
the attributes of the methods that seem relevant (and the event handler) in
my class that does all the work - also to no avail.

Lastly, I've replaced the wait with a sleep loop. which I would have
thought would stand some chance of working. but no.

Sorry. still stuck.

Iain

Dmitriy Lapshin said:
Hi,

As your application is most likely marked with [STAThread], the events
raised by the COM object are handled on the single UI thread your
application has. Once you block the UI thread with WaitOne(), it will never
be able to process further events from the COM object.

--
Dmitriy Lapshin [C# / .NET MVP]
X-Unity Test Studio
http://x-unity.miik.com.ua/teststudio.aspx
Bring the power of unit testing to VS .NET IDE
 
D

Dmitriy Lapshin [C# / .NET MVP]

You can try the following. In the .NET application, launch a separate thread
that would only wait for an event. When the event is set, this thread would
notify the main thread by invoking some method through Form.Invoke() and
immediately exit.

--
Dmitriy Lapshin [C# / .NET MVP]
X-Unity Test Studio
http://x-unity.miik.com.ua/teststudio.aspx
Bring the power of unit testing to VS .NET IDE

Iain said:
I've put a bit of debug code just before the creation of the Com object (and
after the invocation of thee method in the Com object) and the Thread at
those points is MTA.

So it looks like the problem is elsewhere.

The underlying COM object has been coded to work in VB 6 which means that
the events are raised from the main thread (basically the worker thread
sends the event information into a Windows Message loop owned by COM Object.
when this is received it raises the event). So the events are effectively
marshalled on to the initiating thread.

The thread which is doing the writing does not seem visible in the .NET IDE,
however it does continue to operate even after I break the c# stuff.

Iain
Iain said:
Thanks Dmitriy.

But what do I DO?

Obviously the com dll is mutlithreaded ('both'). I've been trying to find
something on this attribute in the docs but haven't hit anything I find
particularly useful. Nor with MTAThread which is what I presume I should
use.

The test program is a windows forms program and I've changed the attribute
on Main() to [MTAThread] which has made no difference. I've also changed
the attributes of the methods that seem relevant (and the event handler) in
my class that does all the work - also to no avail.

Lastly, I've replaced the wait with a sleep loop. which I would have
thought would stand some chance of working. but no.

Sorry. still stuck.

Iain

in message news:[email protected]...
Hi,

As your application is most likely marked with [STAThread], the events
raised by the COM object are handled on the single UI thread your
application has. Once you block the UI thread with WaitOne(), it will never
be able to process further events from the COM object.

--
Dmitriy Lapshin [C# / .NET MVP]
X-Unity Test Studio
http://x-unity.miik.com.ua/teststudio.aspx
Bring the power of unit testing to VS .NET IDE
 
I

Iain

Hmm. I'm trying to get my head round this (sorry, I've taken some time out
to do some higher level stuff, now back to the detail).

Basically, this will end up as a server process - possibly a service, so I
can't rely on UI level stuff like timers of Form.Invoke.

I've taken the waitforone out as an experiment and also the stuff that's
meant to follow afterwards (leaving the code to return to the test UI) and
the events come through fine.

I've tried setting the process of on another thread, but that failed.
Reasonably enough as I guess the thread that could receive the messages is
still locked and therefore will not peek the equivalent of a message loop
(which seems to be the essential problem) - I am by the way, reasonbly
convinced that I could have done this in unmanaged C++ 6 without this class
of problem, though in truth I haven't tried it.

I can't actually see any way of setting of a thread which just waits for the
events. If I block it, it wont get the events, if I don't block it it will
just exit. As mentioned I've tried putting a sleep loop in an it STILL
doesn't get teh events.

What I seem to need is some kind of 'yeild' or message loop functionality.
Is there such - not obvious to a quick look.

This seems an unlikley deficiency in dot net. What am I missing?

Iain
 
D

Dmitriy Lapshin [C# / .NET MVP]

Iain,

I'd suggest receiving *COM* events on the main thread that should never be
blocked. To make the worker thread wait, introduce an AutoResetEvent that
the worker thread would wait for. Thus, the worker thread will be sleeping
until the AutoResetEvent is signaled. And after the event is signaled, the
worker thread will do some useful work and go to sleep until the
AutoResetEvent is signaled for the next time.

The main thread, in turn, will be signaling the AutoResetEvent every time it
receives a COM event. If you need to pass some params to the worker thread
before it starts its work, introduce a thread-safe parameter object
accessible to both threads.

Or, and it might be even better! - you can employ the ThreadPool. Every time
the main thread receives a COM event, it queues a work item on the thread
pool, thus avoiding any "home-made" thread care.

--
Dmitriy Lapshin [C# / .NET MVP]
X-Unity Test Studio
http://x-unity.miik.com.ua/teststudio.aspx
Bring the power of unit testing to VS .NET IDE

Iain said:
Hmm. I'm trying to get my head round this (sorry, I've taken some time out
to do some higher level stuff, now back to the detail).

Basically, this will end up as a server process - possibly a service, so I
can't rely on UI level stuff like timers of Form.Invoke.

I've taken the waitforone out as an experiment and also the stuff that's
meant to follow afterwards (leaving the code to return to the test UI) and
the events come through fine.

I've tried setting the process of on another thread, but that failed.
Reasonably enough as I guess the thread that could receive the messages is
still locked and therefore will not peek the equivalent of a message loop
(which seems to be the essential problem) - I am by the way, reasonbly
convinced that I could have done this in unmanaged C++ 6 without this class
of problem, though in truth I haven't tried it.

I can't actually see any way of setting of a thread which just waits for the
events. If I block it, it wont get the events, if I don't block it it will
just exit. As mentioned I've tried putting a sleep loop in an it STILL
doesn't get teh events.

What I seem to need is some kind of 'yeild' or message loop functionality.
Is there such - not obvious to a quick look.

This seems an unlikley deficiency in dot net. What am I missing?

Iain
Dmitriy Lapshin said:
You can try the following. In the .NET application, launch a separate thread
that would only wait for an event. When the event is set, this thread would
notify the main thread by invoking some method through Form.Invoke() and
immediately exit.

--
Dmitriy Lapshin [C# / .NET MVP]
X-Unity Test Studio
http://x-unity.miik.com.ua/teststudio.aspx
Bring the power of unit testing to VS .NET IDE
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top