2

My coworker likes to do this

if (!listbox1.InvokeRequired)
    listbox1.Items.Add(Container.error_message);
else
    listbox1.Invoke((MethodInvoker)delegate
    {
        listbox1.Items.Add(Container.error_message);
    });

Why do he have to check for InvokedRequired? Will it be better to just use this statement only?

    listbox1.Invoke((MethodInvoker)delegate
    {
        listbox1.Items.Add(Container.error_message);
    });
user3398315
  • 331
  • 6
  • 17

4 Answers4

5

If you are confident that a particular route can only be reached by a callback thread, then I'd be inclined to agree with you - not really for the purpose of avoiding the Invoke, but simply to avoid any duplication. If a path can be reached from multiple routes, it may be preferable to have the check to avoid any overheads in the non-threaded case, but: refactoring so that each code-path knows what it is doing (just calling a utility method) may be preferable, i.e. the UI thread just calls Foo(), where as the worker thread uses Invoke / MethodInvoker to call Foo().

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • +1 I like the utility method route that does the check on `InvokeRequired` and handles accordingly – jordanhill123 Jun 13 '14 at 07:03
  • @jordanhill123 that isn't quite what I was suggesting actually – Marc Gravell Jun 13 '14 at 07:07
  • I agree with your statement but a utility or extension method such as http://stackoverflow.com/questions/2367718/automating-the-invokerequired-code-pattern or http://stackoverflow.com/questions/711408/best-way-to-invoke-any-cross-threaded-code can prevent code duplication. – jordanhill123 Jun 13 '14 at 07:16
2

If you know for sure that the method will be called from a non-GUI thread there's no point in using InvokeRequired.

Furthermore, you could put that listbox1.Items.Add(Container.error_message); into a method (DRY - don't repeat yourself). That method could be called without InvokeRequired from the GUI and by Invoke from a background thread.

Finally, (if at all) the usual pattern would be like so:

void AddMessageToListBox(String message)
{
    if (listbox1.InvokeRequired)
    {
        listbox1.Invoke((Action<String>)AddMessageToListBox, message);
        return;
    }

    listbox1.Items.Add(message);
}
JeffRSon
  • 10,404
  • 4
  • 26
  • 51
1

The InvokeRequired check makes the code work both when run by the GUI thread (executing the first if block) and when run by a non-GUI-thread (the second part of the block).

It looks a bit complicated but if by design the code could be run by either thread it makes sense, at least the Invoke will be necessary. As far as I remember you could choose to use Invoke only as you suggest, it would work when run by the GUI thread, too, but it is probably slightly less efficient. You could possibly argue that this is micro-optimization though - but I suggest that you simply test what happens in either case and how much time it consumes.

chiccodoro
  • 14,407
  • 19
  • 87
  • 130
1
    // Generic delegate for cross thread processing
    private void SetProperty<T>(Control ctrl, string propertyName, T propertyValue)
    {
        if (this.InvokeRequired)
            ctrl.Invoke((Action<Control, string, T>)SetProperty, ctrl, propertyName, propertyValue);
        else
        {
            var property = ctrl.GetType().GetProperty(propertyName);
            property.SetValue(ctrl, propertyValue);
        }
    }

    public object DataSource
    {
        set
        {
            SetProperty(treeView, "DataSource", value);
        }
    }