Handling an ActiveX control that isn't thread safe

J

Julie

So, I have an ActiveX control inside of a Windows Form class.
Apparently, the ActiveX control is not thread safe. So, I'm attempting
to change my code such that only one thread uses the control.

I have a thread that creates the Form with the following line:
Application.Run(new FormClass()); // ActiveX control inside of
FormClass

I had the notion that if I were to create an event in this same thread
to handle all calls to the ActiveX control, then I could fire that
event with other threads, but have this one thread handle all of the
incoming events. The way I implemented the events, however, it appears
that a single thread is not receiving all of the events.
Rather, the thread that fired the event is the one that receives the
event.

How can I implement events such that only one thread receives them? Or
am I going about this all wrong and do you have a better idea?

Thank you!
 
P

Peter Duniho

Julie said:
So, I have an ActiveX control inside of a Windows Form class.
Apparently, the ActiveX control is not thread safe. So, I'm attempting
to change my code such that only one thread uses the control.

I have a thread that creates the Form with the following line:
Application.Run(new FormClass()); // ActiveX control inside of
FormClass

I had the notion that if I were to create an event in this same thread
to handle all calls to the ActiveX control, then I could fire that
event with other threads, but have this one thread handle all of the
incoming events. The way I implemented the events, however, it appears
that a single thread is not receiving all of the events.
Rather, the thread that fired the event is the one that receives the
event.

That's correct. A C# event is, by default, nothing more than a
convenient encapsulation of a multi-cast delegate invocation. And just
as delegate invocations simply make a call into the method being
invoked, so too will events always execute the handlers on the same
thread where the event is raised.
How can I implement events such that only one thread receives them? Or
am I going about this all wrong and do you have a better idea?

You can modify the default behavior of events to do what you want. For
example, using the Control.Invoke() method either in the event handler
or in the method that raises the event itself to execute some particular
code on a given thread (i.e. the thread that owns the Control instance
used to call Invoke()).

It's hard to know for sure from your question what the best approach
would be. But given that you seem to be working in the
System.Windows.Forms namespace, Control.Invoke() probably is the right
way to go.

Pete
 
J

Julie

That's correct.  A C# event is, by default, nothing more than a
convenient encapsulation of a multi-cast delegate invocation.  And just
as delegate invocations simply make a call into the method being
invoked, so too will events always execute the handlers on the same
thread where the event is raised.


You can modify the default behavior of events to do what you want.  For
example, using the Control.Invoke() method either in the event handler
or in the method that raises the event itself to execute some particular
code on a given thread (i.e. the thread that owns the Control instance
used to call Invoke()).

It's hard to know for sure from your question what the best approach
would be.  But given that you seem to be working in the
System.Windows.Forms namespace, Control.Invoke() probably is the right
way to go.

Pete- Hide quoted text -

- Show quoted text -

Thank you! I'm going to try using the Invoke() method.
 
J

Julie

Thank you! I'm going to try using the Invoke() method.- Hide quoted text -

- Show quoted text -

This works beautifully! Although, I'm wondering: what is the best way
to return a value from my Control's function to the caller of Invoke
()? Neither having the function return the value nor passing a
parameter by reference seem to work.
 
J

Julie

This works beautifully! Although, I'm wondering: what is the best way
to return a value from my Control's function to the caller of Invoke
()? Neither having the function return the value nor passing a
parameter by reference seem to work.- Hide quoted text -

- Show quoted text -

Okay, nevermind. It looks like you can return a value from the
function to the caller of Invoke. (For some other unrelated reason,
the value I'm returning isn't right...but I'll have to figure that one
out, I guess.)
 
P

Peter Duniho

Julie said:
This works beautifully! Although, I'm wondering: what is the best way
to return a value from my Control's function to the caller of Invoke
()? Neither having the function return the value nor passing a
parameter by reference seem to work.

Perhaps you can be more explicit about "neither...seem to work".

Passing by reference won't work, but returning a value certainly should.
You'll have to cast the return value, since Control.Invoke() is
declared as returning only "Object", and of course if the return value
is a value type, it will be boxed and unboxed as part of the value
getting returned and cast back to the appropriate type.

But it should work. If you do it right. :)

Pete

(p.s. Actually, I'm lying when I say passing by reference won't
work...my recollection is that by passing an array of arguments to the
Invoke(Delegate, params object[]) method, you can inspect the values in
that array after making the call, where you can find updated values for
things passed by reference. But, that's a lot more complicated and
overkill if all you want is a single return value).
 

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