1

So i've got some code from a GUI program that invokes a delegate via the control.invoke method and now I want to do this in a console.

This is the code:

public class upnpforwarder
{
    List<INatDevice> devices = new List<INatDevice>();

    public upnpforwarder()
    {
        //Hook into the events so you know when a router has been detected or has gone offline
        NatUtility.DeviceFound += DeviceFound;

        //Start searching for upnp enabled routers
        NatUtility.StartDiscovery();
    }

    delegate void AddDeviceDelegate(INatDevice device);
    delegate void RemoveDeviceDelegate(INatDevice device);

    // Adding devices to the list and listbox
    private void AddDevice(INatDevice device)
    {
        if (!devices.Contains(device))
        {
            devices.Add(device);
            IPAddress external = device.GetExternalIP();
            Mapping[] maps = device.GetAllMappings();

            //complicated stuff because the library only allows to display some data via .ToString() as far as I know
            string str = device.ToString();
        }
    }


    // Event that handles a new found device
    private void DeviceFound(object sender, DeviceEventArgs args)
    {
        //Make it thread-safe
        AddDeviceDelegate AddDeviceInstance = new AddDeviceDelegate(this.AddDevice);

        this.Invoke(AddDeviceInstance, new object[] { args.Device });
    }

What is the best alternative method to: this.Invoke(AddDeviceInstance, new object[] { args.Device }); ?

CIGuy
  • 5,076
  • 28
  • 37
  • 1
    Invoke is used to make sure a call happens on the UI thread (rather than a background thread). If you don't have a UI then you don't need to move anything onto the UI thread. Just call the method. – Mike Zboray Aug 13 '13 at 23:41
  • Using control.Invoke is only relevant in a multi-threading situation. Typically when there is one UI thread and one or more worker threads. Do you have multiple threads in the console version of the program? – RenniePet Aug 14 '13 at 00:21

2 Answers2

0

1) The "Invoke" does not make your code thread safe. You probably confused this with an issue of accessing a .NET's UI control from a thread other than UI thread.

2) What is the sense of having a "control" in the UI sense in a console application? An alternative would be to just simply call the method.

If you seek to do this asynchronously then the simplest way is to use TPL.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • But they're not executed in a critical section, so they don't make the executed code thread safe. – BartoszKP Aug 13 '13 at 23:51
  • Yes, you've provided a very good link. Now please read the top-voted answer in it again, carefully. – BartoszKP Aug 14 '13 at 00:01
  • `Invoking a delegate is thread-safe because delegates are immutable` – Arian Motamedi Aug 14 '13 at 00:07
  • But it doesn't make the code that is executed as a result of calling a delegate thread-safe...: "Regarding the execution of the method referenced by the delegate the answer is no." – BartoszKP Aug 14 '13 at 00:09
  • I understand that, but as long as all the threads make their calls through `this.Invoke()`, that would be thread safe, no matter what the delegate to be executed is. – Arian Motamedi Aug 14 '13 at 00:55
  • It would not be thread-safe. For example in the presented code you have a potential race condition on "if (!devices.Contains(device))" when two threads would attempt to add the same device. – BartoszKP Aug 14 '13 at 08:28
0

Control.Invoke is called on the UI thread (the thread that owns the control). Essentially, it is synchronous in your example.

So, just call the delegate directly, or if you need it to be threaded:

Task.Factory.StartNew(() => ..call delegate here ..);
Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138