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());
}
}
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.
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.
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.
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.
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
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).'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With