我有两个程序:客户端(使用WPF)和服务器(控制台应用程序)。服务器可以使用两个线程。客户端向服务器发送“1”或“2”,然后服务器向其发送“3”或“4”。客户端成功获取答案,但由于线程的原因,TextBlock中显示“1”或“2”(过时)。变量“result”始终为“\0”,客户端中的“PropertyChanged”始终为null。
伺服器:
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace Server
{
internal class ServerHandler
{
//private const string _IP = "127.0.0.1";
private const int _PORT = 8888;
private const int _BUFFER_SIZE = 1;
protected internal TcpListener _Listener { get; set; }
protected internal async Task ListenAsync()
{
try
{
//IPAddress localAddr = IPAddress.Parse(_IP);
_Listener = new TcpListener(IPAddress.Any, _PORT);
_Listener.Start();
while (true)
{
Console.WriteLine("oK");
TcpClient tcpClient = await _Listener.AcceptTcpClientAsync();
ClientObject clientObject = new ClientObject(tcpClient);
}
//ClientHandler(_Listener.AcceptTcpClient());
}
catch (SocketException ex)
{
throw new Exception(ex.Message);
}
}
~ServerHandler()
{
if (_Listener != null)
_Listener.Stop();
}
static void Main(string[] args)
{
try
{
ServerHandler handler = new();
handler.ListenAsync();
Console.ReadKey();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
internal class ClientObject
{
protected internal TcpClient _Client { get; set; }
protected internal NetworkStream _Stream { get; set; }
public ClientObject(TcpClient client)
{
_Client = client;
byte[] buffer = new byte[_BUFFER_SIZE];
_Stream = _Client.GetStream();
_Stream.BeginRead(buffer, 0, buffer.Length, EndRead, buffer);
//_Stream.ReadAsync(buffer, 0, buffer.Length);
//_Stream.Write(buffer, 0, buffer.Length);
string result = Encoding.UTF8.GetString(buffer);
//_Stream.WriteAsync(buffer);
SendMessage(result);
}
public void EndRead(IAsyncResult result)
{
byte[] buffer = (byte[])result.AsyncState;
var ns = _Client.GetStream();
var bytesAvalable = ns.EndRead(result);
}
async void SendMessage(string str)
{
try
{
//await Task.Run(() =>
//{
int val;
bool isParsed = Int32.TryParse(str, out val);
if (!isParsed)
return;
if (val != 1 && val != 2)
return;
val = val == 1 ? 3 : 4;
str = val.ToString();
byte[] buffer = Encoding.UTF8.GetBytes(str);
_Stream.WriteAsync(buffer);
_Stream.Flush();
//});
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
字符串
Client.xaml:
<Window x:Class="Client.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Client"
mc:Ignorable="d"
Title="MainWindow" Height="250" Width="300">
<Grid>
<Button x:Name="Button_1" Content="Send" FontSize="15" Width="100" Height="30" Margin="180, 10, 0, 160"
Click="Button_Click" ClickMode="Press">
</Button>
<TextBox x:Name="TextBox_1" MaxLength="50" FontSize="15" Margin="10, 20, 120, 170" TextChanged="TextBox_TextChanged">
</TextBox>
<TextBlock x:Name="TextBlock_1" TextWrapping="Wrap" Margin="10, 90, 10, 100" Text="{Binding Message, Mode=TwoWay}" OpacityMask="#00000000" Background="#FF685959">
</TextBlock>
</Grid>
</Window>
型
Client.xaml.cs:
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Net.Sockets;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Client
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private const string _IP = "127.0.0.1";
private const int _PORT = 8888;
private const int _BUFFER_SIZE = 1;
private TcpClient _Client;
private string _message;
public MainWindow()
{
InitializeComponent();
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
try
{
TextBox textBox = (TextBox)sender;
textBox.MaxLength = 1;
int numVal;
bool isParsed = int.TryParse(textBox.Text, out numVal);
if (isParsed)
{
if (numVal != 1 && numVal != 2)
TextBlock_1.Text = "The value must be 1 or 2!";
else
TextBlock_1.Text = String.Empty;
}
else
{
TextBlock_1.Text = "The value must be 1 or 2!";
}
}
catch (Exception ex)
{
TextBlock_1.Text = ex.Message;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_Client = new TcpClient();
try
{
int numVal;
bool isParsed = int.TryParse(TextBox_1.Text, out numVal);
if (!isParsed)
return;
if (numVal != 1 && numVal != 2)
return;
_Client.ConnectAsync(_IP, _PORT);
// Error
var Stream = _Client.GetStream();
if (Stream != null && TextBox_1.Text != String.Empty)
{
byte[] buffer = new byte[_BUFFER_SIZE];
buffer = Encoding.UTF8.GetBytes(TextBox_1.Text);
SendMessage(Stream, buffer);
byte[] bufferResult = new byte[_BUFFER_SIZE];
Stream.BeginRead(bufferResult, 0, bufferResult.Length, EndRead, bufferResult);
string result = Encoding.UTF8.GetString(bufferResult);
//Binding binding = BindingOperations.GetBinding(TextBlock_1, TextBlock.TextProperty);
Message = result;
}
}
catch (SocketException ex)
{
TextBlock_1.Text = ex.Message;
}
}
public void EndRead(IAsyncResult result)
{
byte[] buffer = (byte[])result.AsyncState;
var ns = _Client.GetStream();
var bytesAvalable = ns.EndRead(result);
}
public void BeginRead(TcpClient Client)
{
try
{
if (Client == null)
return;
byte[] buffer = new byte[_BUFFER_SIZE];
if (Client.Connected)
{
NetworkStream Stream = Client.GetStream();
AsyncCallback callback = null;
callback = ar =>
{
Stream.BeginRead(buffer, 0, buffer.Length, callback, buffer);
};
}
else
{
Client.Connect(_IP, _PORT);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
async void SendMessage(NetworkStream Stream, byte[] buffer)
{
try
{
Stream.Write(buffer, 0, buffer.Length);
string result = Encoding.UTF8.GetString(buffer);
Stream.Flush();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
#region ViewModelProperty: Message
public string Message
{
get
{
return _message;
}
set
{
//_message = value;
_message = "123";
OnPropertyChanged(_message);
}
}
#endregion
#region INotifiedProperty Block
//public event EventHandler SomeEventHappened = delegate { };
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
try
{
PropertyChangedEventHandler handler = PropertyChanged;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
//handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
catch (Exception ex) { }
}
#endregion
}
}
型
最初,我试图使用“TextBlock_1.Text = result”,但它不起作用,值仍然是“1”和“2”。然后我读到我需要使用PropertyChangedEventEvent事件。但它没有帮助。
1条答案
按热度按时间vybvopom1#
这需要正确的INotifyPropertyChanged实现。这意味着每次属性更改时,都需要以Properties名称作为内容触发PropertyChanged事件。在
public string Message
的实现中,您使用值而不是属性名称。所以用途:
字符串
您的接口实现是正确的,如果方法在没有参数的情况下被调用,使用
[CallerMemberName]
将自动插入属性名称:型