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 に書き込む必要があります。

PS。txt オブジェクトは以前は文字列変数でし​​たが、ParameterizedThreadStart私が知っているようにオブジェクトのみをパラメーターとして受け入れるため、変更しました。

どんな助けでも大歓迎です!

前もって感謝します、ジョージ

編集: Abe Heidebrecht が提案したように UpdateTextBox メソッドを編集しました。

4

1 に答える 1

2

通話に問題がいくつかありますInvoke

  • パラメータを渡すためにオブジェクト配列を作成する必要はありません。
  • 受け渡しDispatcherPriority.Normalは冗長です (Normalデフォルトです)。
  • 2番目のメソッドにパラメーターを渡していません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

StackOverflowException無限ループでメソッドを呼び出しているため、これにより a が発生します。これは、メソッドが単に自分自身を何度も呼び出しているために発生しています。

Dispatcher.Invoke所有するスレッドで、渡されたデリゲートを呼び出しますDispatchermsg_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 に答える