1

I can't quite come up with the solution to creating a generic method to handle the InvokeRequired for void methods (I'll deal with return values later). I was thinking something like:

// Probably not the best name, any ideas? :)
public static void CheckInvoke(this Control instance,
                               ,Action<object, object> action)
{
  if (instance.InvokeRequired)
  {
    instance.Invoke(new MethodInvoker(() => action));
  }
  else
  {
    action()
  }
}

Then I could write something like:

public partial class MyForm : Form
{
  private ThreadedClass c = new ThreadedClass();

  public MyForm()
  {
    c.ThreadedEvent += this.CheckInvoke(this
                                        ,this.MethodRequiresInvoke
                                        ,sender
                                        ,e);
  }
}

This doesn't compile obviously, I just can't quite tie it together.

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • Why are you writing code like this? You know you have to use invoke, why bother checking it? – Hans Passant Dec 31 '12 at 22:04
  • 1
    The method being called is being called be either my threaded class (that I don't have control over) or my own code. – Erik Philips Dec 31 '12 at 22:15
  • Just a reference to the same question with more discussion: https://stackoverflow.com/questions/2367718/automating-the-invokerequired-code-pattern – oo_dev Dec 14 '17 at 07:50

2 Answers2

2

Hans is correct, in that you probably don't want to wrap code like this up, especially since it can cause some debugging issues down the road in determining what thread actions are happening on. That said, this would be the signature you'd want:

public static class FormsExt
{
    public static void UnwiseInvoke(this Control instance, Action toDo)
    {
        if(instance.InvokeRequired)
        {
            instance.Invoke(toDo);
        }
        else
        {
            toDo();
        }
    }
}
JerKimball
  • 16,584
  • 3
  • 43
  • 55
  • This is only half the problem, as I can't wire up events to Extension methods. – Erik Philips Dec 31 '12 at 22:20
  • 1
    Well, in this case, as it takes a generic action, you'd have to: c.ThreadedEvent += (o,e) => this.UnwiseInvoke(() => { do stuff }); – JerKimball Dec 31 '12 at 22:30
  • 2
    I would suggest it is better to create an extension method on ISynchronizeInvoke instead of Control. http://msdn.microsoft.com/en-us/library/system.componentmodel.isynchronizeinvoke.aspx – Maarten Jan 01 '13 at 14:36
  • I'm not going to use this. The idea was to make a generic method that was simple, readable and maintainable, but in this state any programmer after me will want to shoot himself. (But it does work!) – Erik Philips Jan 01 '13 at 19:34
  • Well chosen - it *is* code you'll see repeated, and you could make the argument that any code you write more than twice should be encapsulated away, but in this case, the drawbacks (and obfuscated complexity) are a powerful argument **not** to do it. – JerKimball Jan 02 '13 at 00:12
1

Loose Action parameters of "object,object" (as JerKimball suggests), name it SafeInvoke, and attach to event via anonymous delegate:

 c.ThreadedEvent += delegate
                        {
                           c.SafeInvoke(this.MethodRequiresInvoke);
                        };
Algirdas
  • 677
  • 1
  • 6
  • 15