1

I have no trouble using a UDPClient's BeginReceive method from a console application. However, I am not able to get this to run from my WPF app. I'm very confused. I am assuming that it has something to do with where I am calling this code from. I am new to WPF. Is there something I'm misunderstanding about UDPClient's binding in WPF?

Does Inheriting from Application so something that could interfere with UDPClient BeginReceive()

Now this code call stack goes from App.xaml.cs, to ButtonClick(), that creates an instance of MachineItem and calls StartMachine. No weird threading or anything going on (unless WPF does something I'm not aware of during a button click). Again, BeginReceive() is called, but if I put a breakpoint in Receive(IAsyncResult res), nothing ever happens.

public partial class App : Application
{
    //... all the normal stuff here
    private void Button_Click(object sender, RoutedEventArgs e)
    {

        MachineItem currentMachine = (MachineItem)(sender as Button).DataContext;
        currentMachine.StartMachine();
    }
}

Now after button click, this happens:

public class MachineItem : INotifyPropertyChanged
{
    IPEndPoint sendersEndPoint;
    UdpClient listener;

    public void StartMachine()
    {
        listener = new UdpClient
        {
            ExclusiveAddressUse = false
        };

        listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        IPAddress ip = System.Net.IPAddress.Parse(this.LocalNIC_IPAddress);
        int ipInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
        IPEndPoint endPoint = new IPEndPoint(ipInt, 60811); //new IPEndPoint(IPAddress.Any, listenPort); this might allow me not to know the IP of this local device!
        listener.Client.Bind(endPoint);
        listener.BeginReceive(new AsyncCallback(Receive), null);
        Thread.Sleep(20000); // this is just for testing purposes
    }

    private void Receive(IAsyncResult res)
    {
        byte[] bytes = listener.EndReceive(res, ref sendersEndPoint);
        listener.BeginReceive(new AsyncCallback(Receive), null);
        Console.WriteLine("Received");
    }
}

Update: I tried putting this UDP code where the application first starts to further narrow down the problem. I'm still getting the exact same behavior- the Client is able to call BeginReceive(), but then nothing happens even when UDP packets come in, in other words, the async method Receive() is never called...

public partial class WVGUIApp : Application
    {
    IPEndPoint sendersEndPoint;
    UdpClient listener;

    void AppStartup(object sender, StartupEventArgs args)
    {
        LoadMachineData();
        MainWindow mainWindow = new MainWindow();
        mainWindow.Show();

        listener = new UdpClient
        {
            ExclusiveAddressUse = false
        };
        listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        IPAddress ip = System.Net.IPAddress.Parse("10.178.100.111");
        int ipInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
        IPEndPoint endPoint = new IPEndPoint(ipInt, 60811); //new IPEndPoint(IPAddress.Any, listenPort); this might allow me not to know the IP of this local device!
        listener.Client.Bind(endPoint);
        listener.BeginReceive(new AsyncCallback(Receive), null);
        //Thread.Sleep(20000);

    }

    private void Receive(IAsyncResult res)
    {
        byte[] bytes = listener.EndReceive(res, ref sendersEndPoint);
        listener.BeginReceive(new AsyncCallback(Receive), null);
        Console.WriteLine("Received");
    }
}
Goku
  • 1,565
  • 1
  • 29
  • 62
  • @mm8 Done (Good catch), but the problem still exists. – Goku Feb 12 '19 at 16:34
  • 1
    Are you reaching the `Thread.Sleep`? What if you call the `Receive` method? Does it ever return? – mm8 Feb 13 '19 at 15:26
  • I do reach Thread.Sleep. There is no way to call receive that I am aware of to call Receive(IAsyncResult). IAsyncResult is an abstract class. – Goku Feb 13 '19 at 17:04
  • 1
    `Receive` is a method of the `UdpClient` class. – mm8 Feb 14 '19 at 12:47
  • @mm8 Thanks for the clearity. I did a test using this method, and nothing came back. However, I did several experiments and found that a fresh WPF project does NOT have any problems using the code above. But I'm really confused because I'm not sure how to debug this... I put this UDPClient code in my MainWindow, my App.cs, and several other places and I cannot get ANY OF THEM TO WORK! There must be something causing this to not work, but I'm not sure how to proceed with debugging. Sending works, receiving doesn't, but in a new WPF project I have no problems. – Goku Feb 14 '19 at 16:07
  • 1
    If it doesn't return, there is nothing to be received. – mm8 Feb 14 '19 at 16:10
  • Well, In other sample apps I built just for testing this problem out, I am receiving. I have another machine set up next to my computer sending continuous UDP packets to my endpoint in order to debug this problem. – Goku Feb 14 '19 at 16:14
  • @mm8 actually I tried something else out. My code works, but only in release mode... My void Receive(IAsyncResult res) must be getting hit, because I am able to write data to a file in that method, but never hits Receive(IAsyncResult res) method when running in debug mode. This is really confusing the hell out of me. In a sample WPF app I made to help debug this problem, I am able to hit the code even in debug... The code is exactly the same between release and debug – Goku Feb 14 '19 at 16:47

1 Answers1

1

I found the problem after many days of fighting this. The Windows Firewall was not allowing the debug build of the app through. This was hard for me to diagnose because because UDPClient.Send() was allowed, but UDPClient.BeginReceive() was not allowed through the firewall. This is easily fixed on windows 10 by going to Control Panel\All Control Panel Items\Windows Defender Firewall\Allowed apps\ and clicking the name of the app. Release version was allowed through, but debug has a different entry than release. Thank you MM8 for the help with sanity checks.

Goku
  • 1,565
  • 1
  • 29
  • 62