最近真是晕了,事件注册老是注册不上,把情况摘录下来。
一、模块功能
利用Remoting技术广播报警消息,注册的客户端都可以接收到报警信息。
结构:SendAlarm---->AlarmServer---->ReceiveAlarm
ReceiveAlarm类接收到报警在触发自定义事件,这样在主界面报警框类、电子地图上联动报警信息。
二、部分代码
1、远程接口定义
-
C# code
-
namespace KnownObjects { /// <summary> /// 报警结构体 /// </summary> [Serializable] public struct ALARM { public string ipAddress; public string hostName; public string alarmTime; public string alarmMess; } /// <summary> /// 报警客户端 /// </summary> public interface IAlarmClient { /// <summary> /// 消息反馈 /// </summary> /// <param name="message"> A message. </param> object ReceiveMessage(ALARM message); } /// <summary> /// 报警消息通用方法 /// </summary> public interface IAlarmRoom { /// <summary> /// 发送报警信息到所有客户端 /// </summary> /// <param name="message"> Message to send. </param> void SendMessage(ALARM message); /// <summary> /// 注册报警客户端 /// </summary> /// <param name="iAlarmClient"></param> void AttachClient(IAlarmClient iAlarmClient); } }
2、客户接收端
-
C# code
-
namespace ReceiveClient { /// <summary> /// ChatClient demostrates simple client application. /// </summary> public class ReceiveAlarm : MarshalByRefObject, IAlarmClient { public class AlarmMsgEventArgs : EventArgs { // 1. Type defining information passed to receivers of the event public AlarmMsgEventArgs(String ip, String hostname, String mess, String time) { this .ip = ip; this .hostname = hostname; this .mess = mess; this .time = time; } public readonly String ip, hostname,mess,time; } // 报警消息委托 public delegate void AlarmMsgEventHandler(Object sender,AlarmMsgEventArgs args); // 报警消息事件 public event AlarmMsgEventHandler AlarmMsg; // 负责通知事件的登记对象 protected virtual void OnAlarmMsg(AlarmMsgEventArgs e) { // Has any objects registered interest with our event? if (AlarmMsg != null ) { // Yes, notify all the objects AlarmMsg( this , e); } } private IAlarmRoom iAlarmRoom; /// <summary> /// Sigleton instance. /// </summary> public static ReceiveAlarm Instance = new ReceiveAlarm(); public ReceiveAlarm() { } // 连接服务器 public bool InitRemoting() { try { System.Configuration.ConfigurationSettings.GetConfig( " DNS " ); GlobalEventContainer.GenuineChannelsGlobalEvent += new GenuineChannelsGlobalEventHandler(GenuineChannelsEventHandler); RemotingConfiguration.Configure( " Client.exe.config " ); iAlarmRoom = (IAlarmRoom)Activator.GetObject( typeof (IAlarmRoom), " gtcp://127.0.0.1:8737/ChatRoom.rem " ); iAlarmRoom.AttachClient(ReceiveAlarm.Instance); } catch (System.Exception e) { Console.WriteLine( " 异常错误:服务器未启动? " ); return false ; } return true ; } public static void GenuineChannelsEventHandler( object sender, GlobalEventArgs e) { Console.WriteLine( " Global event: {0}, Url: {1}, Exception: {2} " , e.EventType, e.Url, e.SourceException); if (e.EventType == GlobalEventTypes.GTcpConnectionClosed && e.SourceException is OperationException && ((OperationException)e.SourceException).OperationErrorMessage.ErrorIdentifier.IndexOf( " ServerHasBeenRestarted " ) > - 1 ) { // server has been restarted so we have to register our listener again IAlarmRoom iAlarmRoom = (IAlarmRoom)Activator.GetObject( typeof (IAlarmRoom), " gtcp://127.0.0.1:8737/ChatRoom.rem " ); iAlarmRoom.AttachClient(ReceiveAlarm.Instance); } } /// <summary> /// 接收到报警信息.实现了远程接口的方法 /// </summary> /// <param name="message"> The message. </param> public object ReceiveMessage(ALARM message) { /// 测试,接收到消息后触发本地自定义事件,但是有问题,AlarmMsg=null;测试类在后面 AlarmMsgEventArgs e = new AlarmMsgEventArgs(message.ipAddress, message.hostName, message.alarmMess, message.alarmTime); OnAlarmMsg(e); // 这里能够打印出远程传来的信息 Console.WriteLine( " {0},{1},{2},{3} " ,message.ipAddress, message.hostName, message.alarmMess, message.alarmTime); return null ; } public void ArrivingMsg( string ip, string hostname, string mess, string time) { AlarmMsgEventArgs e = new AlarmMsgEventArgs(ip, hostname, mess, time); OnAlarmMsg(e); // Console.WriteLine("Msg...(AppDomain:{0} {1})", AppDomain.CurrentDomain.FriendlyName,mess); } /// <summary> /// This is to insure that when created as a Singleton, the first instance never dies, /// regardless of the expired time. /// </summary> /// <returns></returns> public override object InitializeLifetimeService() { return null ; } } }
3、测试类
-
C# code
-
namespace ReceiveClient { public class Program { static void Main( string [] args) { ReceiveAlarm receive = new ReceiveAlarm(); receive.InitRemoting(); Receiver test = new Receiver(receive); Console.ReadLine(); } } // 测试类 // ReceiveAlarm对象以参数形式传递给测试类, public class Receiver { public Receiver(ReceiveAlarm mm) { // 注册事件 mm.AlarmMsg += new ReceiveAlarm.AlarmMsgEventHandler(RecMsg); } private void RecMsg(Object sender, ReceiveAlarm.AlarmMsgEventArgs e) { Console.WriteLine( " Receiving message: " ); Console.WriteLine( " IP: {0}\n HostName: {1}\n Message: {2}\n Time {3}\n " , e.ip, e.hostname, e.mess, e.time); } public void UnRegister(ReceiveAlarm mm) { mm.AlarmMsg -= new ReceiveAlarm.AlarmMsgEventHandler(RecMsg); } } }
三、解决方法
由于没有访问到触发的报警实例,所以没有注册到。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class Program
{
static void Main(string[] args)
{
ReceiveAlarm receive = new ReceiveAlarm();
receive.InitRemoting();
Receiver rec = new Receiver();
Console.ReadLine();
}
}
public class Receiver
{
/// <summary>
/// 要确保访问到触发的类,所以要使用sigleton
/// </summary>
public Receiver()
{
//receive = new ReceiveAlarm();
//receive.InitRemoting();
//receive.AlarmMsg+=new ReceiveAlarm.AlarmMsgEventHandler(RecMsg);
ReceiveAlarm.Instance.AlarmMsg+=new ReceiveAlarm.AlarmMsgEventHandler(RecMsg);
}
private void RecMsg(Object sender, ReceiveAlarm.AlarmMsgEventArgs e)
{
Console.WriteLine(" Receiving message:");
Console.WriteLine(sender.GetType().ToString());
Console.WriteLine(System.Threading.Thread.CurrentThread.ThreadState.ToString());
Console.WriteLine(" IP: {0}\n HostName: {1}\n Message: {2}\n Time {3}\n", e.ip, e.hostname, e.mess, e.time);
}
public void UnRegister(ReceiveAlarm mm)
{
mm.AlarmMsg -= new ReceiveAlarm.AlarmMsgEventHandler(RecMsg);
}
}
四、总结
当实例化多个类,就不能控制要访问的类。这是要考虑使用Sigleton模式
public class myClass
{
public static myClass instance=new myClass();
public myClass()
{}
}