Problem with Weird InvokeRequired

I have a UserControl with a TreeView control called mTreeView. I can receive data updates from several different streams, and this leads to a TreeView update. To do this, I developed the following template: all data update event handlers should get a lock, and then check InvokeRequired; if so, do the work by calling Invoke. Here is the relevant code:

  public partial class TreeViewControl : UserControl
  {  
    object mLock = new object();
    void LockAndInvoke(Control c, Action a)
    {
      lock (mLock)
      {
        if (c.InvokeRequired)
        {
          c.Invoke(a);
        }
        else
        {
          a();
        }
      }
    }

    public void DataChanged(object sender, NewDataEventArgs e)
    {
      LockAndInvoke(mTreeView, () =>
        {
          // get the data
          mTreeView.BeginUpdate();
          // perform update
          mTreeView.EndUpdate();
        });
    }    
  }

, , , InvalidOperationException mTreeView.BeginUpdate(), , mTreeView , , . LockAndInvoke, , c.InvokeRequired , else ! InvokeRequired true , else.

- , , ?

EDIT: , , InvokeRequired , , . , . ?

+5
3

. , TreeView . , InvokeRequired false , . , Load Load, , , .

btw. , InvokeRequired, Begin/Invoke . InvokeRequired - -. , . InvokeRequired , . .

+6

, , 100% ( , , , ).

., , , , mTreeView , , , mTreeView , .

, - .

, , , mTreeView , . , 100% , , , , , , .

+1

, - . Invoke.

Invoke , . , . BeginInvoke . , Invoke, , -, : :

private bool b;
public void EventHandler(object sender, EventArgs e)
{
  while(b) Thread.Sleep(1); // give up time to any other waiting threads
  if(InvokeRequired)
  {
    b = true;
    Invoke((MethodInvoker)(()=>EventHandler(sender, e)), null);
    b = false;
  }
}

... while, Invoke , EventHandler , EventHandler , b ...

Pay attention to my use of bool to stop the execution of certain sections of code. This is very similar to locking. So yes, you might have a dead end with locking.

Just do the following:

public void DataChanged(object sender, NewDataEventArgs e)
{
      if(InvokeRequired)
      {
          BeginInvoke((MethodInvoker)(()=>DataChanged(sender, e)), null);
          return;
      }
      // get the data
      mTreeView.BeginUpdate();
      // perform update
      mTreeView.EndUpdate();
}

It simply re-calls the DataChanged method asynchronously in the user interface thread.

+1
source

All Articles