Marshalling (ie PostMessage) in C#.

  • Thread starter Thread starter Gregory Goeppel
  • Start date Start date
G

Gregory Goeppel

I have a component (with NO user interface) in C# that
fires events from a seperate thread. The client of the C#
component does processing with UI elements and other non
thread safe variables within these events. I do NOT want
the client to be processing the event from the secondary
thread created in the component. I want it to process from
the Main UI thread.

I have scanned through MSND documentation and it keeps
saying to use control.BeginInvoke() in the client to do
this. However requiring the client of my component to do
this is one more thing that can go wrong for users of my
component. So I want it performed from within the
component. In C++ I could acheive this by using PostMessage
() specifying an HWND in the main thread.


How do I do this in C# from within the component that is
invisible at runtime. My component object does not have a
BeginInvoke on it. Should I create a hidden control from
within the component simply to marshall back to main
thread from within itself?

Any Ideas would be appreciated. TIA
-Greg.
 
Gregory,

What you want to do is expose some sort of method or property that will
take an implementation of the ISynchronizeInvoke interface. This interface
is used to synchronize the events that one would want to fire on an object.
For windows controls, it does exactly what you would do, posting a message
to the UI thread for a control to handle.

However, this isn't the only way to synchronize events, so the interface
is used to abstract that. What your component should do is take an instance
of this interface and then make the calls to Invoke on that interface. All
you have to say is where the affinity lies by passing in the appropriate
implementation.

Hope this helps.
 
Thanks,

Here's what I did and it works great! The control object
provides an implementation of ISynchronizeInvoke. So I
instance it in the components main thread. So what ever
thread in the client creates the component that thread
should get affinity.

private Control m_ControlInMainThread;

private void startPopupAlertThread()
{
//We are in Components Main Thread Now

m_ControlInMainThread = new Control();
m_ControlInMainThread.CreateControl();
ThreadStart entryPoint = new ThreadStart
(GetPopUpAlertsThread);
Thread popupAlertThread = new Thread(entryPoint);
popupAlertThread.Start();
}

Now from the Alert Thread I can do the following

//Post this Event back to Main Thread!
m_ControlInMainThread.BeginInvoke(m_WebCtrlPopupHandler,
new object[] {alert});

Now My Thread ID's show that the Handler in the client
matches the Main UI thread in which I instance the
component from the client.

If there are any reasons you can think of that I shouldn't
be doing things this way, let me know. So far in my
testing it works great.

Thanks Again,
Greg.

-----Original Message-----
Gregory,

What you want to do is expose some sort of method or property that will
take an implementation of the ISynchronizeInvoke interface. This interface
is used to synchronize the events that one would want to fire on an object.
For windows controls, it does exactly what you would do, posting a message
to the UI thread for a control to handle.

However, this isn't the only way to synchronize events, so the interface
is used to abstract that. What your component should do is take an instance
of this interface and then make the calls to Invoke on that interface. All
you have to say is where the affinity lies by passing in the appropriate
implementation.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Gregory Goeppel said:
I have a component (with NO user interface) in C# that
fires events from a seperate thread. The client of the C#
component does processing with UI elements and other non
thread safe variables within these events. I do NOT want
the client to be processing the event from the secondary
thread created in the component. I want it to process from
the Main UI thread.

I have scanned through MSND documentation and it keeps
saying to use control.BeginInvoke() in the client to do
this. However requiring the client of my component to do
this is one more thing that can go wrong for users of my
component. So I want it performed from within the
component. In C++ I could acheive this by using PostMessage
() specifying an HWND in the main thread.


How do I do this in C# from within the component that is
invisible at runtime. My component object does not have a
BeginInvoke on it. Should I create a hidden control from
within the component simply to marshall back to main
thread from within itself?

Any Ideas would be appreciated. TIA
-Greg.


.
 
Back
Top