分类广告


推荐文章

  • 没有找到任何内容!
您当前的位置:中国站长下载网络编程NET专区 → 文章内容

Microsoft .Net Remoting系列专题之三:Remoting事件处理全接触5

  • 作者:佚名    来源:不详    发布时间:2007-6-30 10:22:15
  • 字体大小:
     然后我们在服务端单击“BroadCast”按钮,发送广播消息:
  


  击“Send”发送,再来看看客户端,会是怎样?Fine,I got it!
  
  怎么样,很酷吧!你也可以同时打开多个客户端,它们都将收到这个广播信息。如果你觉得这个广播声音太吵,那就请你在客户端取消广播吧。在Cancle按钮中:
  private void btnCancle_Click(object sender, System.EventArgs e)
  {
   watch.BroadCastEvent -= new BroadCastEventHandler(wrapper.BroadCasting);
   MessageBox.Show("取消订阅广播成功!");
  }
  当然这个时候wrapper对象应该被申明为private对象了:
  private EventWrapper wrapper = null;
  
  
  
  取消后,你试着再广播一下,恭喜你,你不会听到噪音了!
  
  三、 客户端订阅客户端事件
  
  有了前面的基础,再来看客户端订阅客户端事件,就简单多了。而本文写到这里,我也很累了,你也被我啰嗦得不耐烦了。你心里在喊,“饶了我吧!”其实,我又何尝不是如此。所以我只提供一个思路,有兴趣的朋友,可以自己写一个程序。
  
  其实方法很简单,和第二种情况类似。发送信息的客户端,只需要获得远程对象后,发送消息就可以了。而接收信息的客户端,负责订阅该事件。由于事件都是放到远程对象中,因此订阅的方法和第二种情况没有什么区别!
  
  特殊的情况是,我们可以用第三种情况来代替第二种。只要你把发送信息的客户端放到服务端就可以了。当然需要做一些额外的工作,有兴趣的朋友可以去实现一下。在我的示例程序中,已经用这种方法模拟实现了服务端的广播,大家可以去看看。
  
  四、 一点补充
  
  我在前面的事件处理中,使用的都是默认的EventArgs。如果要定义自己的EventArgs,就不相同了。因为该信息是传值序列化,因此必须加上[Serializable],且必须放到公共程序集中,部署到服务端和客户端。例如:
  [Serializable]
  public class BroadcastEventArgs:EventArgs
  {
   private string msg = null;
   public BroadcastEventArgs(string message)
   {
   msg = message;
   }
  
   public string Message
   {
   get {return msg;}
   }
  }
  
  五、持续改进(经Beta的提醒,我改进了我的程序,并对文章进行了修改 2004年12月13日)
  
  也许,细心的读者注意到了,在我的远程对象类和EventWrapper类中,触发事件方法的Attribute[OneWay]被我注释掉了。我看到很多资料上写到,在Remoting中处理事件,触发事件的方法必须具有这个Attribute。这个attribute究竟有什么用?
  
  在发送事件消息的时候,事件的订阅者会触发事件,然后响应该事件。然而当事件的订阅者发生错误的时候呢?例如,发送事件消息的时候,才发现根本没有事件订阅者;或者事件的订阅者出现故障,如断电、或异常关机。此时,发送事件一方会因为找不到正确的事件订阅者,而发生异常。以我的程序为例。当我们分别打开服务端和客户端程序的时候,此时广播信息正常。然而,当我们关闭客户端后,由于该客户端没有取消订阅,此时异常发生,提示信息如图:
  
  
  不知道为什么,这个异常与客户端连接服务端出现的异常一样。这个异常容易让人产生误会。)
  
  如果这个时候我们同时打开了多个客户端,那么其他客户端就会因为这一个客户端关闭造成的错误,而无法收到广播信息。那么让我们先做第一步改进:
  
  1、先考虑正常情况。在我的客户端,虽然提供了取消订阅的操作,但并没有考虑用户关闭客户端的情况。即,关闭客户端时,并未取消事件的订阅,所以我们应该在关闭客户端窗体中写入:
  
  Word-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
   private void ClientForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
   {
   watch.BroadCastEvent -= new BroadCastEventHandler(wrapper.BroadCasting);
   }
  2、仅仅是这样还不够。如果客户端并没有正常关闭,而是因为突然断电而导致客户端关闭呢?此时,客户端还没有来得及取消事件订阅呢。在这种情况下,我们需要用到OneWayAttribute。
  
  前面说到,发送事件一方如果找不到正确的事件订阅者,会发生异常。也就是说,这个事件是unreachable的。幸运的是,OneWayAttribute恰好解决了这个问题。其实从该特性的命名OneWay,大约也能猜到其中的含义。当事件不可到达,无法发送时,正常情况下,会返回一个异常信息。如果加上OneWayAttribute,这个事件的发送就变成单向的了。假如此时发生异常,那么系统会自动抛掉该异常信息。由于没有异常信息的返回,发送信息方会认为发送信息成功了。程序会正常运行,错误的客户端被忽略,而正确的客户端仍然能够收到广播信息。
  
  因此,远程对象的代码就应该是这样: