Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF-调用其他类时GUI不更新?(TCP应用程序)_C#_Wpf_Tcp_Controls_Textblock - Fatal编程技术网

C# WPF-调用其他类时GUI不更新?(TCP应用程序)

C# WPF-调用其他类时GUI不更新?(TCP应用程序),c#,wpf,tcp,controls,textblock,C#,Wpf,Tcp,Controls,Textblock,我有一个相当奇怪的问题?我在web上见过如何将控件从主类传递到另一个类,据说这是可行的,但事实并非如此 我试图做的是创建一个简单的异步TCP客户机-服务器连接,它将消息从客户机发送到服务器。问题是当我想更新客户端的文本块时,应用程序退出(并没有错误,只是关闭)。我只有一个主线程,所以我认为不需要调用 来自主类的代码: public partial class MainWindow : Window { public MainWindow() { Initial


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

来自主类的代码:

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";
        }
    }

来自其他类的代码:

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";
        }
    }
公共类异步客户端
{
//远程设备的端口号。
专用静态int端口;
专用静态IP地址;
公共静态文本块状态面板;
公共静态无效setStatusPanel(文本块状态)
{
statusPanel=status;//这是我要更新的statusPanel的setter
}          
公共静态void StartClient(字符串消息)
{
//连接到远程设备。
尝试
{
IPAddress IPAddress=ipAd;
IPEndPoint remoteEP=新IPEndPoint(ipAddress,端口);
套接字客户端=新套接字(AddressFamily.InterNetwork,
流,ProtocolType.Tcp);
client.BeginConnect(remoteEP,
新的异步回调(ConnectCallback),客户端);
connectDone.WaitOne();
字符串sendingMessage=消息+“”;
发送(客户端,发送消息);
sendDone.WaitOne();
接收(客户);
receiveDone.WaitOne();
client.Shutdown(SocketShutdown.Both);
client.Close();
}
捕获(例外e)
{
statusPanel.Text+=e.ToString()+“\n”;
}
}
专用静态无效连接回调(IAsyncResult ar)
{
尝试
{
套接字客户端=(套接字)ar.AsyncState;
客户端.EndConnect(ar);
//下一行是我的程序无误关闭的地方
statusPanel.Text=“套接字已连接到”+客户端.RemoteEndPoint.ToString()+“\n”;
connectDone.Set();
}
捕获(例外e)
{
statusPanel.Text+=e.ToString()+“\n”;
}
}
**如果我将“statusPanel.text”替换为“Console.WriteLine”,一切正常!有人知道我做错了什么吗?***

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

因此,您必须将其委托给主线程,如下所示:

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

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


使用
StatusOanel.Dispatcher.Invoke
在UI线程上执行您的方法。如果您想了解更多有关它的信息,本文可能是这样的:

我尝试使用statusPanel.Dispatcher(您发布的代码)但它不起作用。UI冻结了!问题出在您的代码中的某个地方。很可能是在
BeginInvoke
操作之后,您正在这里等待一些线程
sendDone.WaitOne()
receiveDone.WaitOne();
。尝试注释这些行(仅用于测试以确定问题)并查看问题是否仍然存在。如果我将.Invoke更改为.BeginInvoke,则会得到client.RemoteEndPoint.ToString()的错误(无法访问已释放的对象)。那么,我如何告诉线程先完成更新,然后再继续?不,我不是要将Invoke更改为BeginInvoke。它必须是Invoke only。我的意思是当您调用委托
client.BeginConnect(remoteEP,新的异步回调(ConnectCallback),client)时;
。在这一行之后,你调用多个方法,并使用
WaitOne
等待它们,但我没有看到你从代码中设置这些WaitOne,因此你的UI线程将继续等待它们,直到你设置它们。试着注释代码,看看这是否是问题所在。我发布的代码肯定不会挂起UI。你是对的。是WaitOne()和线程停止!