开发者

Why are my events firing when not assigned to any control/was never assigned to specific control?

So I have this bit of code that refreshes controls on a form to reflect register states in a connected device. In this code, I use MethodInvoker to perform the process into another thread such as to not lock up the entire UI, kind of an asynchronous refresh. Anyways, in this MethodInvoker body, I first "-= new EventHandler(this._assignedEvent)", disable the control, update one of it's properties based on the device register status, and re-enable the control, and reassign the EventHandler.

I have replicated this several times throughout my current project, and about 90% of the time, this works. However for a about three/four controls I have on a particular form this is what happens:

  1. Remove event for control x
  2. Modify control x
  3. Event for control y is fired, event was never assigned to x, ever.
  4. Event for control x is fired
  5. me = confused

And this only happens to a few select controls and I was wondering if there was some cross thread execution rules that I didn't adhere to or something...

The refresh code in question looks something like below:

if (_prbsRxLockTime.Enabled)
            {
                ParentDevice.Dongle.Read((RxSelect() == 0 ? _registers.PRBS_RX_2 : _registers.PRBS_RX_16).Offset.ToString("X"), ref result, 1);
                bitMask = (ushort)(Bit.B0 | Bit.B1 | Bit.B2 | Bit.B3);

                UpdateControlUsingMethod(new MethodInvoker(
                    () =>
                    {
                        this._prbsRxLockTime.SelectedIndexChanged -= new System.EventHandler(this._prbsRxLock_SelectedIndexChanged);
                        this._prbsRxLockTime.Enabled = false;
                        foreach (object i in _prbsRxLockTime.Items)
                        {
                            KeyValuePair<string, ushort> item = (KeyValuePair<string, ushort>)i;
                            if ((ushort.Parse(result, NumberStyles.HexNumber) & bitMask) == (ushort)(item.Value))
                            {
                                _prbsRxLockTime.SelectedItem = i;
                                break;
                            }
                        }
                        this._prbsRxLockTime.Enabled = true;
                        this._prbsRxLockTime.SelectedIndexChanged += new System.EventHandler(this._prbsRxLock_SelectedIndexChanged);
                    }
                ));
            }

The event that is fired upon modifying _prbsRxLockTime.SelectedItem is this:

private void _prbsRxLOL_SelectedIndexChanged(object sender, EventArgs e)
    {
        ushort comboBoxData = (ushort)(((ComboBox)sender).SelectedValue);
        ushort bitMask = (ushort)(Bit.B0 | Bit.B1 | Bit.B2 | Bit.B3);
        string regAddress = string.Empty;
        string regData = comboBoxData.ToString("X").PadLeft(4, '0');

        switch (((ComboBox)sender).Name)
       开发者_如何学Go {
            case "_prbsRxLOLTime":
                regAddress = (RxSelect() == 0 ? _registers.PRBS_RX_5 : _registers.PRBS_RX_19).Offset.ToString("X");
                break;
            case "_prbsRxLOLThresh":
                regAddress = (RxSelect() == 0 ? _registers.PRBS_RX_6 : _registers.PRBS_RX_20).Offset.ToString("X");
                break;
            default:
                break;
        }

        ParentDevice.Dongle.Modify(regAddress, regData, 1, bitMask);
    }1.4.


I suggest you to read this Methodinvoker Invoke For a GUI App thread and this Safe,Simple Multithreading in WinForms article for checking if you are using methodinvoker correctly.

It may also be helpful to suggest you an alternative solution if you explain when and by who the first code block is triggered to run.

Edit After Comments

Sorry but it is difficult to suggest anything because of not having all source codes. It looks like an event subscriber left somewhere in your code or having a problem related to events and multi-threading environment like Events and Deadlocks (See Comments Section)

Another suggestion may be an alternative solution such as using a flag rather than controling event subscription which has some side-affects. You can create a thread-safe property which indicates the updating progress that should not handle by the SelectedIndexChanged procedures.

UpdateControlUsingMethod(new MethodInvoker(
    () =>
    {
        //this._prbsRxLockTime.SelectedIndexChanged -= new System.EventHandler(this._prbsRxLock_SelectedIndexChanged);
        this._prbRxLockTimeUpdatingByThread = true;

        //the code has been omitted here

        //this._prbsRxLockTime.SelectedIndexChanged += new System.EventHandler(this._prbsRxLock_SelectedIndexChanged);
        this._prbRxLockTimeUpdatingByThread = false;
    }
));

and then you can check that property in your event handler for not running the standard procedure.

private void _prbsRxLOL_SelectedIndexChanged(object sender, EventArgs e)
{
    if (this._prbRxLockTimeUpdatingByThread)
        return;

    //the code has been omitted here
}

Hope this help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜