WPF - GUI在调用不同类时不会更新? (TCP应用程序)

时间:2014-08-24 07:11:09

标签: c# wpf tcp controls textblock


我有一个相当奇怪的问题?我在网上看到如何将控制从主类传递到另一个类,据说这可以工作,但事实并非如此?
我要做的是创建一个简单的异步TCP客户端 - 服务器连接,它将从客户端发送到服务器的消息。问题是当我想要更新客户端的文本块时,应用程序退出(没有错误就会关闭)。我只有一个主线程,所以我不认为我需要一个Invoke。

主类代码:

public partial class MainWindow : Window
{


    public MainWindow()
    {
        InitializeComponent();
    }

    private void connect_ClickEvent(object sender, RoutedEventArgs e)
    {
        try
        {
            _statusPanel.Text += "Sending request to server (IP address: " + _ipTextBox.Text + ", port number: " + _portTextBox.Text + ")\n";
            _statusPanel.Text += "Connecting.....\n";

            AsynchronousClient.setStatusPanel(_statusPanel);
            AsynchronousClient.setPort(Convert.ToInt32(_portTextBox.Text));
            AsynchronousClient.setIpAddress(_ipTextBox.Text);
            AsynchronousClient.StartClient(_message.Text);

            _statusPanel.Text += "... connection established!\n";
            _statusPanel.Text += "Enter the string to be transmitted !\n";
        }
        catch (Exception ee)
        {
            _statusPanel.Text += ee.StackTrace + "\n";
        }

    }

}


来自其他类的代码:

public class AsynchronousClient
{
    // The port number for the remote device.
    private static int port;
    private static IPAddress ipAd;
    public static TextBlock statusPanel;

    public static void setStatusPanel(TextBlock status)
    {
        statusPanel = status; //That's my setter for statusPanel which I want to update
    }          

    public static void StartClient(string message)
    {
        // Connect to a remote device.
        try
        {
            IPAddress ipAddress = ipAd;
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            Socket client = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            client.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();

            string sendingMessage = message + "<EOF>";
            Send(client, sendingMessage);
            sendDone.WaitOne();

            Receive(client);
            receiveDone.WaitOne();

            client.Shutdown(SocketShutdown.Both);
            client.Close();

        }
        catch (Exception e)
        {
            statusPanel.Text += e.ToString() + "\n";
        }
    }

    private static void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            Socket client = (Socket)ar.AsyncState;

            client.EndConnect(ar);

            //This next line is where my program closes without error
            statusPanel.Text = "Socket connected to " + client.RemoteEndPoint.ToString() + "\n";

            connectDone.Set();

        }
        catch (Exception e)
        {
            statusPanel.Text += e.ToString() + "\n";
        }
    }

**如果我更换&#34; statusPanel.text&#34;使用&#34; Console.WriteLine&#34;一切正常!谁知道我做错了什么? **

2 个答案:

答案 0 :(得分:1)

AsyncCallback将在单独的线程上调用,而不是在主线程上调用 ,因此您无法从其他线程更新textBox值。您只能从主UI线程执行此操作。

所以,你必须在主线程上委托它:

statusPanel.Dispatcher.Invoke(new Action(() => 
                     statusPanel.Text = "Socket connected to " + 
                     client.RemoteEndPoint.ToString() + "\n"));

答案 1 :(得分:0)

您的方法ConnectCallback将不会在WPF用户界面线程上执行,而是由线程池的后台线程上的套接字类调用。在此方法中,您可以设置StatusPanel

的文本

使用StatusOanel.Dispatcher.Invoke在UI线程上执行您的方法。如果您想了解更多相关信息,可以参考本文:http://msdn.microsoft.com/en-us/magazine/gg598924.aspx