App freezes after Dispatcher.Invoke

10,315

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).'

Share:
10,315
Kevin k5
Author by

Kevin k5

Updated on July 06, 2022

Comments

  • Kevin k5
    Kevin k5 almost 2 years

    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());
            }
        }
    
  • Kevin k5
    Kevin k5 over 10 years
    @ mark thank you so much...i used the BeginInvoke but the application is now freezing in the syntax ( theReply = reader.readString()) in the loop..
  • Mark Travis
    Mark Travis over 10 years
    @ Kevin K5. I have ammended the answer to include why reader.ReadString may be freezing your application.