我有一个相当奇怪的问题?我在网上看到如何将控制从主类传递到另一个类,据说这可以工作,但事实并非如此?
我要做的是创建一个简单的异步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;一切正常!谁知道我做错了什么? **
答案 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