应用程序在Dispatcher.Invoke之后冻结

Kev*_* k5 5 c# sockets wpf multithreading

我有这个应用程序在调用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!");
        }


    }
Run Code Online (Sandbox Code Playgroud)

当代码进入方法(检查连接)并调用调度程序时,应用程序冻结.

     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());
        }
    }
Run Code Online (Sandbox Code Playgroud)

Mar*_*vis 9

Dispatcher.Invoke试图同步运行的调度程序线程指定的操作.

假设RunClient在Dispatcher Thread上运行,并且while循环在您尝试重新调用Dispatcher Thread时继续运行,则调用将冻结.

最简单的解决方案是使用Dispatcher.BeginInvoke替换所有Dispatcher.Invoke,并为其设置一个优先级,该优先级将在RunClient完成后运行.

另一种解决方案是在运行RunClient BackgroundWorker的.

有答案的类似问题是

  1. Dispatcher.Invoke循环冻结UI
  2. Dispatcher.Invoke挂起主窗口.

回应对ReadString冻结的评论

在NetworkStream上调用Read是一个阻塞调用.嗯,实际上,它是通过调用阻塞的TcpClient.GetStream()获得的Stream .MSDN上的文档说明' 获得NetworkStream后,调用Write方法将数据发送到远程主机.调用Read方法以接收从远程主机到达的数据.这两种方法都会阻塞,直到执行指定的操作为止.

我使用dotPeek来查看ReadString正在做什么,它首先要做的是使用NetworkStream.ReadByte从流中读取传入字符串的长度,它将阻塞直到它有一个要读取的值.

这意味着ReadString将一直存在,直到有可读数据,数据量与预期相同或更多.您将需要检查,如果您有任何你通过调用之前做阅读stream.DataAvailablereader.PeekChar.

或者,您可以在单独的线程上运行套接字代码.如果你使用.Net 4.5,我会好好看看任务并行库.ntziolis在回答这个问题时说," 我们已经取得了很好的经验(长期是几天而不是几分钟或几小时)."