这两天翻了很多关于回调资料,后来才恍然大悟,贴上来说下解决方案。
1. 回调接口声明
public interface ICallback
{
[OperationContract(IsOneWay = true)] // 回调操作也必须One Way
void CallbackToClient(DateTime timestamp, string message);
}
2.回调使用
/// <summary>
/// 设置服务行为为单例模式,即所有客户端共享一个服务实例
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyTagService : IService
{
static List<ICallback> m_Callbacks = new List<ICallback>();
public void AddMessage(string message)
{
m_Callbacks.ForEach(callback =>
{
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
callback.CallbackToClient(DateTime.Now, message);
else
m_Callbacks.Remove(callback);
});
}
/// <summary>
/// read from plc and update local value
/// </summary>
/// <param name="plcTag">需要读取PLC的变量</param>
/// <returns>无</returns>
public string Read_PLC_Tag(PLCTag tag)
{
string value=plc.TagValue(tag);
if (ServerMessageGot != null)
{
ServerMessageGot(this, new MessageReceiveEventArgs(DateTime.Now,tag.Address.ToString() + "-" + tag.DataSize.ToString() + "-" + value.ToString()));
}
AddMessage(tag.Address.ToString() + "-" + tag.DataSize.ToString() + "-" + value.ToString()); //回调
return value;
}
}
3. 回调事件
///<summary>
///实现回调接口
///</summary>
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class MyCallback : ICallback
{
/// <summary>
// 回调后触发该事件,用于通知客户端
/// </summary>
public event EventHandler<MessageReceiveEventArgs> ValueCallbacked = delegate { };
// 因为该方法是由服务器调用的
// 如果希望在客户端能即时作出响应
// 应当使用事件
public void CallbackToClient(DateTime timestamp, string message)
{
MessageReceiveEventArgs e = new MessageReceiveEventArgs(timestamp,message);
if (this.ValueCallbacked != null)
{
this.ValueCallbacked(this, e);
}
}
}
4.客户端回调
public class Client
{
IService ClientChanel;
DuplexChannelFactory<IService> channelFactory;
MyCallback Callback = new MyCallback();
/// <summary>
/// 服务端对客户端的消息通知
/// </summary>
public event EventHandler<MessageReceiveEventArgs> ServerMessageReceived = delegate { };
public Client(string ServerName)
{
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.None;
InstanceContext instanceContext = new InstanceContext(Callback);
channelFactory = new DuplexChannelFactory<IService>(instanceContext, binding, new EndpointAddress("net.tcp://" + ServerName + ":2970/PLCTagServices/"));
ClientChanel=channelFactory.CreateChannel();
ClientChanel.Subscribe();
channelFactory.Faulted += new EventHandler(channelFactory_Faulted);
Callback.ValueCallbacked+=new EventHandler<MessageReceiveEventArgs>(Callback_ValueCallbacked);
}
void Callback_ValueCallbacked(object sender,MessageReceiveEventArgs e)
{
ServerMessageReceived(this, e);
}
}