当UI发生更改时,我试图让一个WPF应用程序与另一个应用程序通信。例如:滑条发生变化,我发送新值,或者文本框输入发生变化,我发送新的输入值。
第二个应用程序正在侦听并接收这些更改以更新不同的属性。
要实现此目的,我将根据文档中的Actor模式示例使用NetMQ:https://netmq.readthedocs.io/en/latest/actor/
现在我有这些Client / Server类:
服务器:
public class NetMQServer
{
public class ShimHandler : IShimHandler
{
private PairSocket shim;
private NetMQPoller poller;
private PublisherSocket publisher;
private string Address;
public ShimHandler(string address)
{
Address = address;
}
public void Initialise(object state)
{
}
public void Run(PairSocket shim)
{
using (publisher = new PublisherSocket())
{
publisher.Bind(Address);
publisher.Options.SendHighWatermark = 1000;
this.shim = shim;
shim.ReceiveReady += OnShimReady;
shim.SignalOK();
poller = new NetMQPoller { shim, publisher };
poller.Run();
}
}
private void OnShimReady(object sender, NetMQSocketEventArgs e)
{
string command = e.Socket.ReceiveFrameString();
if(command == NetMQActor.EndShimMessage)
{
poller.Stop();
return;
}
else
{
byte[] byteMessage = e.Socket.ReceiveFrameBytes();
publisher.SendMoreFrame(command).SendFrame(byteMessage);
}
}
private void UpdateString(string stringmessage, string propertyToUpdate)
{
propertyToUpdate = stringmessage;
}
}
public NetMQServer(string ip, int port)
{
IP = ip;
Port = port;
Serializer = new CerasSerializer();
}
public CerasSerializer Serializer { get; set; }
private NetMQActor actor;
private string _name;
public string Name
{
get { return _name; }
set { _name = value;}
}
private int _port;
public int Port
{
get { return _port; }
set
{
_port = value;
ReStart();
}
}
private string _ip;
public string IP
{
get { return _ip; }
set
{
_ip = value;
ReStart();
}
}
public string Address
{
get { return String.Format("tcp://{0}:{1}", IP, Port); }
}
public void Start()
{
if (actor != null)
return;
actor = NetMQActor.Create(new ShimHandler(Address));
}
public void Stop()
{
if (actor != null)
{
actor.Dispose();
actor = null;
}
}
public void ReStart()
{
if (actor == null)
return;
Stop();
Start();
}
public void SendObject(string topic, object commandParameter)
{
if (actor == null)
return;
byte[] Serialized = Serializer.Serialize(commandParameter);
var message = new NetMQMessage();
message.Append(topic);
message.Append(Serialized);
actor.SendMultipartMessage(message);
}
}
在这里,当控件的属性发生更改时,我调用SendStringMessage(string stringToSend)
函数并与NetMQ发布者一起发送(该字符串仅用于测试,我也可以将任何对象作为字节发送)。
无论如何,这是在第二个应用程序上运行的客户端:
public class NetMQClient
{
public class ShimHandler : IShimHandler
{
private PairSocket shim;
private NetMQPoller poller;
private SubscriberSocket subscriber;
private ByteMessage ByteMessage;
private string Address;
private string Topic;
private string MessageType;
public ShimHandler(ByteMessage byteMessage, string address, string topic)
{
this.ByteMessage = byteMessage;
this.Address = address;
this.Topic = topic;
}
public void Initialise(object state)
{
}
public void Run(PairSocket shim)
{
using (subscriber = new SubscriberSocket())
{
subscriber.Connect(Address);
subscriber.Subscribe(Topic);
subscriber.Options.ReceiveHighWatermark = 1000;
subscriber.ReceiveReady += OnSubscriberReady;
this.shim = shim;
shim.ReceiveReady += OnShimReady;
shim.SignalOK();
poller = new NetMQPoller { shim, subscriber };
poller.Run();
}
}
private void OnSubscriberReady(object sender, NetMQSocketEventArgs e)
{
string topic = e.Socket.ReceiveFrameString();
if (topic == Topic)
{
this.ByteMessage.Message = e.Socket.ReceiveFrameBytes();
}
}
private void OnShimReady(object sender, NetMQSocketEventArgs e)
{
string command = e.Socket.ReceiveFrameString();
if (command == NetMQActor.EndShimMessage)
{
poller.Stop();
}
}
}
public ByteMessage ByteMessage { get; set; }
private NetMQActor actor;
private string _command;
public string Command
{
get { return _command; }
set { _command = value;}
}
private string _topic;
public string Topic
{
get { return _topic; }
set
{
_topic = value;
ReStart();
}
}
private int _port;
public int Port
{
get { return _port; }
set
{
_port = value;
ReStart();
}
}
private string _ip;
public string IP
{
get { return _ip; }
set
{
_ip = value;
ReStart();
}
}
public string Address
{
get { return String.Format("tcp://{0}:{1}", IP, Port); }
}
public NetMQClient(string ip, int port, string topic)
{
ByteMessage = new ByteMessage();
IP = ip;
Port = port;
Topic = topic;
}
public void Start()
{
if (actor != null)
return;
actor = NetMQActor.Create(new ShimHandler(ByteMessage, Address, Topic));
}
public void Stop()
{
if (actor != null)
{
actor.Dispose();
actor = null;
}
}
public void ReStart()
{
if (actor == null)
return;
Stop();
Start();
}
}
现在ByteMessage类看起来像这样简单:
public class ByteMessage : INotifyPropertyChanged
{
public ByteMessage()
{
}
private byte[] _message;
public byte[] Message
{
get { return _message; }
set
{
_message = value;
OnPropertyChanged("Message");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
第二个应用程序类将拥有一个NetMQClient作为属性,并注册到NetMQClient的OnPropertyChange
的{{1}}事件中。
现在,从ByteMessage
更新了ByteMessage.Message
之后,我就可以反序列化数据并对其进行处理。
到目前为止,这是可行的,但我真的不确定我是否做得正确...以及是否为ShimHandler
如果Listening应用程序上的每个类都具有自己的NetMQClient来监听特定主题,那会更好吗?
即使在阅读了围绕NetMQ提供的所有示例之后,也真的混淆了如何使用所有这些内容。
谢谢