应用程序冻结后Dispatcher.Invoke [英] App freezes after Dispatcher.Invoke
问题描述
我有这样的应用程序中调用任何控制的dispatcher.invoke时冻结。
当我打电话给调度员在单选按钮,网格Image..etc的应用冻结但不给错误。任何帮助,请!谢谢
我所说的线程方法RunClient
私人无效RunClient ()
{
TcpClient的客户端;
//实例化的TcpClient将数据发送到服务器
试
{
//第1步:创建TcpClient的,并连接到服务器
客户端=新的TcpClient();
client.Connect(IP,5001);
//第2步:获取的NetworkStream与TcpClient的
输出= client.GetStream有关();
//创建写入和跨流
作家=新的BinaryWriter(输出)读取对象;
=读者新BinaryReader(输出);
串theReply =;
做
{
试
{
//读取发送到服务器
theReply = reader.ReadString字符串();
INT I = 0;
的foreach(在theReply.Split变种X('#'))
{
ReadString [I] = X;
I ++;
}
CheckConnection(ReadString [0]);
}
赶上(例外)
{
//什么也不做
}
}而(ReadString [6] .Equals()及与放大器;
connection.Connected);
updatelabel =()=> GameResult(ReadString [6]);
Dispatcher.Invoke(新动作(updatelabel));
如果(connection.Connected!)
{
MessageBox.Show(连接中断比赛将被自动关闭。);
writer.Close();
reader.Close();
output.Close();
的Connection.close();
this.Close();
}
}
//处理异常,如果错误在建立连接
赶上(例外错误)
{
MessageBox.Show(检查Internet连接无法连接)。!;
}
}
在代码进入方法(检查连接),并调用调度应用程序冻结。
无效CheckConnection(串II)
{
试
{
如果(ii.Equals(已连接))
{
MessageBox.Show(成立一个Connection);
INT X = Convert.ToInt32(ReadString [1]);
如果(X == 1)
{
updatelabel =()=> char1RadioButton2.IsEnabled = FALSE;
char1RadioButton2.Dispatcher.Invoke(新动作(updatelabel));
}
,否则
{
updatelabel =()=> char5RadioButton2.IsEnabled = FALSE;
char5RadioButton2.Dispatcher.Invoke(新动作(updatelabel));
}
updatelabel =()=> CreatingGameGrid.Visibility = System.Windows.Visibility.Visible;
CreatingGameGrid.Dispatcher.Invoke(新动作(updatelabel));
updatelabel =()=> JoinGameGrid.Visibility = System.Windows.Visibility.Visible;
JoinGameGrid.Dispatcher.Invoke(新动作(updatelabel));
}
,否则
{
MessageBox.Show(没有这样的游戏找到);
this.Close();
}
}
赶上(例外X)
{
MessageBox.Show(x.ToString());
}
}
的 Dispatcher.Invoke尝试的同步的上运行调度程序线程指定的操作。
假设RunClient是在调度线程运行,并且同时继续循环,而你正在试图调用回送到Dispatcher线程来运行,呼叫将冻结。
最简单的解决办法是更换所有Dispatcher.BeginInvoke的Dispatcher.Invoke并给它,这将运行一次您的RunClient完成当务之急。
其他的解决办法是在的 BackgroundWorker的。
与答案
的 回应有关ReadString冻结评论的
电话阅读上的NetworkStream是一个阻塞调用。唉,其实,它是通过调用的 TcpClient.GetStream ()的块。在MSDN文档状态的您已经获得的NetworkStream之后,调用Write方法将数据发送到远程主机。调用read方法来接收来自远程主机到达的数据。这两种方法都被阻塞,直到指定的操作被执行的'。
我用 dotPeek 来看看有什么ReadString在做,它做的第一件事是读取使用的 NetworkStream.ReadByte 这将阻止,直到它有一个数值来读取。
这意味着ReadString会坐在那里直到有可供读取的数据和数据的量相同或比预期更。您将需要检查,如果您有任何调用的 stream.DataAvailable 或的 reader.PeekChar 。
另外,你可以在一个单独的线程中运行你的套接字代码。如果您正在使用.NET 4.5,我会采取在href=\"http://msdn.microsoft.com/en-us/library/dd537609.aspx\">任务并行库的 ntziolis 说,在回答这个的我们已经与(长天被而非数分钟或数小时),取得了良好的经验>问题的。
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());
}
}
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).'
这篇关于应用程序冻结后Dispatcher.Invoke的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!