我有这个应用程序在调用dispatcher.invoke进行任何控制时冻结。
当我在radiobutton,Grid,Image ..etc中调用Dispatcher时,应用程序冻结但没有出错。任何帮助请!!!谢谢
我调用线程方法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!");
}
}
当代码进入方法(检查连接)并调用调度程序时,应用程序会冻结。
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());
}
}
答案 0 :(得分:9)
Dispatcher.Invoke attempts to synchronously在Dispatcher Thread上运行指定的操作。
假设RunClient在Dispatcher Thread上运行,而while循环在你尝试重新调用Dispatcher Thread时继续运行,则调用将冻结。
最简单的解决方案是将所有Dispatcher.Invoke替换为Dispatcher.BeginInvoke,并为其设置一个优先级,该优先级将在RunClient完成后运行。
另一种解决方案是在BackgroundWorker上运行RunClient。
回答的类似问题是
对ReadString冻结评论的回复
调用NetworkStream上的Read是一个阻塞调用。嗯,事实上,它是通过调用阻塞TcpClient.GetStream()获得的Stream。 MSDN上的文档说明'获取NetworkStream后,调用Write方法将数据发送到远程主机。调用Read方法以接收从远程主机到达的数据。这两种方法都会阻塞,直到执行指定的操作'。
我使用dotPeek来查看ReadString正在做什么,它首先要做的是使用NetworkStream.ReadByte从流中读取传入字符串的长度,它将阻塞直到它有一个要读取的值。
这意味着ReadString将一直存在,直到有数据可供读取且数据量与预期相同或更多。在致电stream.DataAvailable或reader.PeekChar之前,您需要先检查一下是否有任何需要阅读的内容。
或者,您可以在单独的线程上运行套接字代码。如果您使用的是.Net 4.5,我会好好看一下Task Parallel Library。 ntziolis在对此question的回答中说'我们已经为此做了很好的经历(长期是几天而不是几分钟或几小时)。'