Hello, I am seeing something I do not understand while using Control.BeginInvoke to update a WinForms form in response to an event from a backgraound thread. The app is written in Managed C++. There are four classes involved: 1) a MyMonitor class that has a timer that goes off every second or so, and examines the state of a device, firing its Pressed event when it needs to 2) a MyController class that sinks the MyMonitor Pressed event (as well as events from other stuff), and maps it to its own DevicePressed event 3) a MyPressedEventArgs class, contained device state info, a new instance of which is passed when the DevicePressed event is raised 4) a MyForm class that sinks the DevicePressed event and makes UI changes
Both the Pressed and DevicePressed events are EventHandler delegates. The behavior I do not understand is: when I use BeginInvoke to cause the UI update handler to run in the form's thread, the actual parameters are always a reference to the MyForm instance and an empty System Object, no matter what I put in the Object array passed in BeginInvoke.
The actual code looks like:
void MyForm::DevicePressedEventHandler (Object* sender, EventArgs* e)
{
if (InvokeRequired) {
EventHandler* handler = new EventHandler(this, &MyForm::DevicePressed_UI_Update);
MyPressedStateArgs* args = dynamic_cast<MyPressedStateArgs*> (e); // <-A
if (args != NULL) {
Object* arr[] = { sender, e };
BeginInvoke(handler, arr); //<-B
}
} else {
DevicePressed_UI_Update(sender, e);
}
}
void MyForm::DevicePressed_UI_Update (Object* sender, EventArgs* e)
{
MyPressedStateArgs* args = dynamic_cast<MyPressedStateArgs*> (e); // <-C
if (args == NULL)
return;
// *update UI, based on pressed state*
}
At point A, where the DevicePressed event from MyController class is being signaled/handled in a background thread, the debugger shows that e is a MyPressedEventArgs instance with the correct state as passed in. At point B, the debugger shows the (sender, e) being stored. At point C, where the UI update routine is being run in the form's main thread, the debugger shows that sender is a reference to the MyForm instance (even if I pass something else in the array's first spot), and e is always an empty System::Object (no matter what is in the array's second spot).
I use the above pattern in dozens of places in my UI code, and it (appears to) work perfectly.
Any thoughts?
Phil Coveney