Firing an event from a worker thread in a component

D

Doug Bright

Hello all,

I'm trying to build a .NET component the fires events from a worker
thread, and I'm getting running into problems with the whole "controls
must be modified only on the calling thread" issue. There were a
couple of well known techniques for dealing with this through a COM
interface, but, despite how easy it seems with .NET, I'm still having
some trouble.

In this particular case, the component is written in C++ and the
client I'm testing with is a simple VB.NET application. The technique
I'm trying to use is to call Invoke() on all the delegates in the
event's invocation list in order to marshal the call to the UI thread.
I apparently do not fully understand what I'm doing since a quick
check of InvokeRequired() in the event handling code invariably
returns true.

I've created a small sample project to illustrate the problem. Please
let me know if you see any glaring errors I'm making:

C++ component:

public __gc class EventSource : public Component
{
public:
__delegate void MyEventHandler(Object *sender, EventArgs *e);
__event MyEventHandler* OnMyEvent;
virtual void FireEvent()
{
if(OnMyEvent != NULL)
{
Delegate *delegates[] = OnMyEvent->GetInvocationList();
for(Int32 i = 0; i < delegates->Count; i++)
{
MyEventHandler *sink = (MyEventHandler*)delegates;
sink->Invoke(this, EventArgs.Empty);
}
}
}

void StartEventFiringThread()
{
Thread *EventFiringThread= new Thread(new ThreadStart(this,
FireEvent));
EventFiringThread->IsBackground = true;
EventFiringThread->Start();
}
};


VB client code:

Private Sub EventSource1_OnMyEvent(ByVal sender As Object, ByVal e As
System.EventArgs) Handles EventSource1.OnMyEvent
If TextBox1.InvokeRequired() Then
Debug.Assert(False) 'ALWAYS HIT THIS ASSERTION
End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click
EventSource1.StartEventFiringThread()
End Sub



The above code always produces the assertion. If I change the
EventSource1.StartEventFiringThread() call to EventSource1.FireEvent()
(that is, to fire event on the same thread) the problem goes away as I
would expect.

Thanks for any insight into this issue.

Doug
 
D

Doug Bright

I'm sorry, I also failed to mention that the VB code belongs to a
customer and therefore I cannot simply change the VB code to use
Invoke() on controls. The customer is also unwilling to make the
change so I must find away around this in the component itself (note
that this is a component and NOT a control so I can't just call Invoke
on myself either).
 

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