0

It's a lot of irrelevant code to look through.. but pretty much it sends a packet and listens for a packet in return

if i comment the part out where it calls the ReceiveAuthPacket() method at the end of sending a packet, it will work and the label will turn blue.. but otherwise it will never activate turning the label blue and will instead turn the label red or green (depending on the returned packet).

basically im just using the label as an indicator of the status.. and no matter what i try i can't get it to turn blue because it seems to be waiting for all the code to be finished executing and it just won't work..

i even tried using data triggers in WPF and it still won't work.

any work arounds? i just don't get it..

        private readonly UdpMessageAuthentication _msgAuth;        

        private void Button_Authenticate_OnClick(object sender, RoutedEventArgs e)
        {
            Label_Authentication.Content = "Attempting Authentication";
            Label_Authentication.Foreground = new SolidColorBrush(Colors.Blue);

            _msgAuth.SendAuthPacket(IPAddress.Parse(TextBox_IP.Text), TextBox_ClientID.Text);
        }

        public void SendAuthPacket(IPAddress ip, string userID)
        {
            _ip = ip;
            _userID = userID;
            if (_udpClient.Client == null)
                _udpClient = new UdpClient();

            //GSISClockRegRequest,<Client Id>,,1 
            string msg = string.Format("GSISClockRegRequest,{0},,1", _userID);
            byte[] sendBytes = Encoding.ASCII.GetBytes(msg);
            bool sent = false;

            try
            {
                _label.Content = "Attempting Authentication";
                _label.Foreground = new SolidColorBrush(Colors.Blue);

                while (_label.Content != "Attempting Authentication")
                {
                    //loop
                }

                _udpClient.Connect(_ip, 5001);
                _udpClient.Send(sendBytes, sendBytes.Length);
                Console.WriteLine("Sending {0} bytes.  Message: {1}", sendBytes.Length, msg);
                sent = true;
            }
            catch (Exception)
            {
                Console.WriteLine("UDP Auth Packet Failed to Send");
            }

            _udpClient.Close();

            if (sent)
                ReceiveAuthPacket();  //IF I COMMENT THIS OUT IT'LL WORK
        }

        private void ReceiveAuthPacket()
        {
            IPEndPoint e = new IPEndPoint(IPAddress.Any, 5001);
            UdpClient u = new UdpClient(e);
            u.Client.ReceiveTimeout = 3000;
            Console.WriteLine("Listening for Messages: ");

            try
            {
                Byte[] receiveBytes = u.Receive(ref e);
                string receiveString = Encoding.ASCII.GetString(receiveBytes);
                Console.WriteLine("Received: {0}", receiveString);

                string errMsg = "";
                if (AuthMessageParser.ParseMessage(receiveString, ref errMsg))
                {
                    _label.Content = "Authentication Successful!";
                    _label.Foreground = new SolidColorBrush(Colors.Green);
                }
                else
                {
                    _label.Content = "Authentication Unsuccessful: " + errMsg;
                    _label.Foreground = new SolidColorBrush(Colors.Red);
                }

            }
            catch (Exception)
            {
                _label.Content = "Authentication Unsuccessful";
                _label.Foreground = new SolidColorBrush(Colors.Red);
                Console.WriteLine("UDP Auth Packet was NOT Received.");
            }

            u.Close();
        }
user1189352
  • 3,628
  • 12
  • 50
  • 90
  • 1
    `Byte[] receiveBytes = u.Receive(ref e);` is a blocking call, you are blocking the UI from updating. Fixing it easily depends on the version .net you are using. Are you using .net 4.5 or 4.0 with the Microsoft.Bcl.Async library? – Scott Chamberlain May 20 '14 at 16:58
  • hm i suspected something like that.. is there something i can do to force the label first? or some sort of work around? – user1189352 May 20 '14 at 16:59
  • possible duplicate of [Label takes long time to change](http://stackoverflow.com/questions/23753616/label-takes-long-time-to-change) – nvoigt May 20 '14 at 16:59

1 Answers1

3

Your UI thread is blocked by calls to things like _udpClient.Connect() and _udpClient.Send() (and the receives, too)

A workaround would be to leverage the task parallel library and perform communications asynchronously to avoid blocking the UI thread.

It will manage threads for you as long as you define tasks properly. Holler if you need an example.

protected void SomeButton_Click(Object sender, EventArgs e)
{
    // Task off the work and do not wait, no blocking here.
    Task.Run(PerformConnection);
}

private async Task PerformConnection()
{
    // This method acts the way a thread should.  We await the result of async comms.
    // This will not block the UI but also may or may not run on its own thread.
    // You don't need to care about the threading much.
    var conn = await ListenerOrSomething.AwaitConnectionsAsync( /* ... */ );

    // Now you have your result because it awaited.
    using(var newClient = conn.Client())
    {
        var buffer = new byte[];           
        var recv = await newClient.ReceiveAsyncOrSomething(out buffer);

        // Data received is not zero, process it or return
        if(recv > 0)
            newClient.Response = await ProcessRequest(buffer);
        else
            return;
    }
}
clarkitect
  • 1,720
  • 14
  • 23
  • I think it is the receiveing action not the sending action that is blocking him. – Scott Chamberlain May 20 '14 at 17:01
  • ya an example would be nice.. so should i just open a new thread to handle the label change and call dispatcher? – user1189352 May 20 '14 at 17:02
  • Funny, I added note of those to the answer a few moments ago as well. And you're right, @Scott, those are probably the first in line to block the UI. – clarkitect May 20 '14 at 17:02
  • Don't open a new thread, just a new task. That will let the TPL manage thread pooling and scheduling for you. I'll throw an example into my answer. – clarkitect May 20 '14 at 17:02
  • can you also explain the difference? i'd like to understand why this works as opposed to a thread for example just for knowledge reasons, thanks! – user1189352 May 20 '14 at 17:04
  • 1
    I explained some in comments. There's [docs for the task parallel library](http://goo.gl/DGQuXg) to read but the short answer is that a task can be managed by the TPL asynchronously without blocking your thread. Your tasks _may_ run on their own thread but you don't need to do all the thread management yourself. – clarkitect May 20 '14 at 17:10
  • Why start a task with `StartNew`? Make `PerformConnection()` `async Task`, make the event handler `async void`, and then `await` `PerformConnection` in the event handler. `async void` should **never** be used except for event handlers. There's tons of documentation on why out there. – Daniel Mann May 20 '14 at 17:18
  • @DanielMann why block the UI thread by awaiting? It's true we could make that first method a task but it doesn't need to return any information to the button click event at all so ... why await? And, if we're not awaiting, why complicate the method signature? Also, how would you await `void`? – clarkitect May 20 '14 at 17:19
  • 2
    @Jeffdot `await`ing doesn't block the UI thread. That's the entire point. Making the method return `Task` instead of `void` doesn't "complicate" the method signature -- it's how you're supposed to implement the pattern. http://msdn.microsoft.com/en-us/magazine/jj991977.aspx – Daniel Mann May 20 '14 at 17:23
  • I'll modify my answer because you're not wrong (and it will match the examples in the docs, that's a good point) but I'm still going to maintain that it --so far-- adds only complication and no actual value . – clarkitect May 20 '14 at 17:26
  • @jeffdot I suggest you do some serious reading on the Task Asynchronous Pattern, then. I'm getting the impression that you don't really understand it. – Daniel Mann May 21 '14 at 04:14