0

我正在尝试使用 WPF 创建一个多客户端/服务器聊天小应用程序,但我遇到了一些问题。不幸的是,当我按下连接按钮时,程序崩溃了。

好吧,到目前为止,我是使用客户端程序(使用线程)完成的: public delegate void UpdateText(object txt);

我得到了那个方法:

    private void UpdateTextBox(object txt)
    {
        if (msg_log.Dispatcher.CheckAccess())
        {
            Dispatcher.Invoke(new UpdateText(UpdateTextBox),txt);

        }
        else
        {
            msg_log.Dispatcher.Invoke(new UpdateText(UpdateTextBox), txt);
        }
    }

我正在使用 Button_Click 事件像这样连接到服务器:

        private void connect_Click(object sender, RoutedEventArgs e)
        {
        if ((nick_name.Text == "") || (ip_addr.Text == "") || (port.Text == ""))
        {
            MessageBox.Show("Nick name, IP Address and Port fields cannot be null.");
        }
        else
        {

            client = new Client();
            client.ClientName = nick_name.Text;
            client.ServerIp = ip_addr.Text;
            client.ServerPort = port.Text;
            Thread changer = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(UpdateTextBox));
            changer.Start();
            client.OnClientConnected += new OnClientConnectedDelegate(client_OnClientConnected);
            client.OnClientConnecting += new OnClientConnectingDelegate(client_OnClientConnecting);
            client.OnClientDisconnected += new OnClientDisconnectedDelegate(client_OnClientDisconnected);
            client.OnClientError += new OnClientErrorDelegate(client_OnClientError);
            client.OnClientFileSending += new OnClientFileSendingDelegate(client_OnClientFileSending);
            client.OnDataReceived += new OnClientReceivedDelegate(client_OnDataReceived);
            client.Connect();

        }
    }

请注意 OnClient* 事件就像private void client_OnDataReceived(object Sender, ClientReceivedArguments R) { UpdateTextBox(R.ReceivedData); }

所以这些事件应该在 msg_log TextBox 中写入一些像“Connected”这样的文本

PS。txt 对象曾经是一个字符串变量,但我更改了它,因为ParameterizedThreadStart我知道只接受对象作为参数。

任何帮助将不胜感激!

在此先感谢,乔治

编辑:按照 Abe Heidebrecht 的建议编辑了 UpdateTextBox 方法。

4

1 回答 1

2

Invoke你的电话有一些问题。

  • 您不需要创建对象数组来传递参数。
  • 传递DispatcherPriority.Normal是多余的(Normal默认)。
  • 您没有将任何参数传递给第二种Invoke方法(这可能是您发生错误的地方)。

它应该如下所示:

private void UpdateTextBox(object txt)
{
    if (msg_log.Dispatcher.CheckAccess())
    {
        Dispatcher.Invoke(new UpdateText(UpdateTextBox), txt);
    }
    else
    {
        msg_log.Dispatcher.Invoke(new UpdateText(UpdateTextBox), txt);
    }
}

编辑StackOverflowException

这将导致 aStackOverflowException因为您在无限循环中调用您的方法。发生这种情况是因为您的方法只是一遍又一遍地调用自己。

什么Dispatcher.Invoke是在拥有Dispatcher. 仅仅因为msg_log可能有不同的调度程序,当您调用 时UpdateTextBox,您将委托传递给当前方法,这会导致无限循环。

您真正需要做的是在 msg_log 对象上调用一个方法,如下所示:

private void UpdateTextBox(object txt)
{
    if (msg_log.Dispatcher.CheckAccess())
    {
        if (txt != null)
            msg_log.Text = txt.ToString();
    }
    else
    {
        msg_log.Dispatcher.Invoke(new UpdateText(UpdateTextBox), txt);
    }
}
于 2013-06-27T16:49:38.167 回答