Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

App freezes after Dispatcher.Invoke

I have this application that freezes when calling the dispatcher.invoke for any control.

When i Call the Dispatcher in radiobutton, Grid, Image..etc the App freezes but without giving errors. any help please !!! thank you

I call the thread Method RunClient

private void RunClient()
    {

        TcpClient client;

        // instantiate TcpClient for sending data to server
        try
        {
            // Step 1: create TcpClient and connect to server

            client = new TcpClient();
            client.Connect(ip, 5001);

            // Step 2: get NetworkStream associated with TcpClient
            output = client.GetStream();

            // create objects for writing and reading across stream
            writer = new BinaryWriter(output);
            reader = new BinaryReader(output);

            string theReply = "";

            do
            {
                try
                {
                    // read the string sent to the server
                    theReply = reader.ReadString();

                    int i = 0;

                    foreach (var x in theReply.Split('#'))
                    {
                        ReadString[i] = x;
                        i++;
                    }

                    CheckConnection(ReadString[0]);



                }
                catch (Exception)
                {
                    //do nothing
                }

            } while (ReadString[6].Equals(" ") &&
                   connection.Connected);

            updatelabel = () => GameResult(ReadString[6]);
            Dispatcher.Invoke(new Action(updatelabel));

            if (!connection.Connected)
            {
                MessageBox.Show("The connection was lost. The game will be closed automatically.");
                writer.Close();
                reader.Close();
                output.Close();
                connection.Close();
                this.Close();
            }

        }
        // handle exception if error in establishing connection
        catch (Exception error)
        {
            MessageBox.Show("Check Internet Connectivity. Couldn't connect!");
        }


    }

when the code enters the method ( check connection ) and calls the dispatcher the app freezes.

     void CheckConnection(string ii)
    {
        try
        {
            if (ii.Equals("Connected"))
            {
                MessageBox.Show("A Connection was established");




                int x = Convert.ToInt32(ReadString[1]);

                if (x == 1)
                {

                    updatelabel = () => char1RadioButton2.IsEnabled = false;
                    char1RadioButton2.Dispatcher.Invoke(new Action(updatelabel));
                }

                else
                {
                    updatelabel = () => char5RadioButton2.IsEnabled = false;
                    char5RadioButton2.Dispatcher.Invoke(new Action(updatelabel));
                }


                updatelabel = () => CreatingGameGrid.Visibility = System.Windows.Visibility.Visible;
                CreatingGameGrid.Dispatcher.Invoke(new Action(updatelabel));



                updatelabel = () => JoinGameGrid.Visibility =        System.Windows.Visibility.Visible;
                JoinGameGrid.Dispatcher.Invoke(new Action(updatelabel));

            }
            else
            {
                MessageBox.Show("No Such Game found");
                this.Close();
            }
        }
        catch (Exception x)
        {
            MessageBox.Show(x.ToString());
        }
    }
like image 575
Kevin k5 Avatar asked Dec 27 '13 13:12

Kevin k5


People also ask

What does dispatcher invoke do?

Invoke(DispatcherPriority, TimeSpan, Delegate)Executes the specified delegate synchronously at the specified priority and with the specified time-out value on the thread the Dispatcher was created.

Is dispatcher invoke synchronous?

Invoke is synchronous and BeginInvoke is asynchronous. The operation is added to the event queue of the Dispatcher at the specified DispatcherPriority. If multiple BeginInvoke calls are made at the same DispatcherPriority, they will be executed in the order the calls were made.

What is dispatcher C#?

The Dispatcher maintains a prioritized queue of work items for a specific thread. When a Dispatcher is created on a thread, it becomes the only Dispatcher that can be associated with the thread, even if the Dispatcher is shut down.

How does WPF dispatcher work?

WPF Dispatcher is associated with the UI thread. The UI thread queues methods call inside the Dispatcher object. Whenever your changes the screen or any event executes, or call a method in the code-behind all this happen in the UI thread and UI thread queue the called method into the Dispatcher queue.


1 Answers

The Dispatcher.Invoke attempts to synchronously run the specified action on the Dispatcher Thread.

Assuming the RunClient is run on the Dispatcher Thread, and the while loop continues to run while you are trying to Invoke back onto the Dispatcher Thread, the call will freeze.

The simplest solution is to replace all the Dispatcher.Invoke with Dispatcher.BeginInvoke and give it a priority that will run once your RunClient is finished.

The other solution is to run RunClient on a BackgroundWorker.

Similar questions with answers are

  1. Dispatcher.Invoke loop freeze UI
  2. Dispatcher.Invoke hangs main window.

Response to comment on ReadString freeze

Calling Read on a NetworkStream is a blocking call. Well, in fact, it is the Stream obtained by calling TcpClient.GetStream() that blocks. The documentation on MSDN states 'After you have obtained the NetworkStream, call the Write method to send data to the remote host. Call the Read method to receive data arriving from the remote host. Both of these methods block until the specified operation is performed'.

I used dotPeek to see what ReadString was doing and the first thing it does is read the length of the incoming string off the stream using NetworkStream.ReadByte which will block until it has a value to read.

That means the ReadString will sit there until there is data available to read and the amount of data is the same as or more than is expected. You will need to check if you have anything to read before you do by calling stream.DataAvailable or reader.PeekChar.

Alternatively, you could run your socket code on a separate thread. If you are using .Net 4.5, I would take a good look at the Task Parallel Library. ntziolis says in an answer to this question that 'We have made good experiences with that (long being days rather than minutes or hours).'

like image 122
Mark Travis Avatar answered Oct 27 '22 00:10

Mark Travis