Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Events over .Net Remoting

Events over .Net Remoting

Scheduled Pinned Locked Moved C#
csharpsysadminjsonhelp
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mikke_x
    wrote on last edited by
    #1

    Hi all, I have a problem I cannot solve by my own. The message is quite long, but I hope that someone is nice enough to read it and give me a hand. The basic problem is that I cannot sent events over .Net remoting that has an event argument as a class I have created, but strings as arguments works just fine. I have three projects: Server, Middle and Client. Server going to generate events and pass them through .Net remoting to the client. The middle project contains the remoted object. It also contains a delegate that is used to define the events generated in the server. The server is remoting the class in the middle project through a TCP channel. The connection class in the server is remoting the object: private void OpenConnection() { BinaryClientFormatterSinkProvider clientProvider = null; BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; IDictionary props = new Hashtable(); props["port"] = 7889; props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; props["name"] = "StatusControl"; TcpChannel chan = new TcpChannel( props,clientProvider,serverProvider); ChannelServices.RegisterChannel(chan); RemotingConfiguration.RegisterWellKnownServiceType( Type.GetType("ProductionStatusControl.DistributedStatusControl, ProductionStatusControl"),"IDistributedControl", WellKnownObjectMode.Singleton ); // Singleton class used to retreive messages from the remoted objects m_single = StatusSingletonConnection.GetInstance(); System.Threading.ThreadStart ts = new System.Threading.ThreadStart( SendMessages ); System.Threading.Thread t = new System.Threading.Thread( ts ); t.IsBackground = true; t.Start(); } The middle project has a delegate: public delegate void ProductionStatusDelegate( StatusMessage message ); , a class as event argument: /// /// A status message from the floating storage /// [Serializable] public class StatusMessage { private FloatingStorageEventType m_type; private string m_message; /// /// Creates a new Status message instance /// /// /// public StatusMessage( FloatingStorageEventType type, string message ) { this.m_message = message; this.m_type = type; }

    T 1 Reply Last reply
    0
    • M Mikke_x

      Hi all, I have a problem I cannot solve by my own. The message is quite long, but I hope that someone is nice enough to read it and give me a hand. The basic problem is that I cannot sent events over .Net remoting that has an event argument as a class I have created, but strings as arguments works just fine. I have three projects: Server, Middle and Client. Server going to generate events and pass them through .Net remoting to the client. The middle project contains the remoted object. It also contains a delegate that is used to define the events generated in the server. The server is remoting the class in the middle project through a TCP channel. The connection class in the server is remoting the object: private void OpenConnection() { BinaryClientFormatterSinkProvider clientProvider = null; BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; IDictionary props = new Hashtable(); props["port"] = 7889; props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; props["name"] = "StatusControl"; TcpChannel chan = new TcpChannel( props,clientProvider,serverProvider); ChannelServices.RegisterChannel(chan); RemotingConfiguration.RegisterWellKnownServiceType( Type.GetType("ProductionStatusControl.DistributedStatusControl, ProductionStatusControl"),"IDistributedControl", WellKnownObjectMode.Singleton ); // Singleton class used to retreive messages from the remoted objects m_single = StatusSingletonConnection.GetInstance(); System.Threading.ThreadStart ts = new System.Threading.ThreadStart( SendMessages ); System.Threading.Thread t = new System.Threading.Thread( ts ); t.IsBackground = true; t.Start(); } The middle project has a delegate: public delegate void ProductionStatusDelegate( StatusMessage message ); , a class as event argument: /// /// A status message from the floating storage /// [Serializable] public class StatusMessage { private FloatingStorageEventType m_type; private string m_message; /// /// Creates a new Status message instance /// /// /// public StatusMessage( FloatingStorageEventType type, string message ) { this.m_message = message; this.m_type = type; }

      T Offline
      T Offline
      Tom Larsen
      wrote on last edited by
      #2

      Events conceptually are not sound in any network protocol. I'm surprised there was even an attempt in .Net Remoting to support this. The exception you are seeing is somewhat indicitive of the general problem. I wish that future versions of .Net Remoting would throw a more accurate exception than ArgumentException you often see in this case. Okay so what is the problem? Mechanically, it can't serialize the delegate and event cleanly across .Net Remoting. Seriously, how would .Net Remoting even begin to handle an delegates/events? Ignore the actual mechanical problems with serialization for a moment and look at the concept you are trying to do. Bare with my crude ascii art :)

      +--------------------------------------------+ +-------------------+

      • Client + + Server +
      •                                        +                  +                   +
        
      • ObjectA CallRemoteB() + ---------------->+ ObjectB Call() +
      • { + + { +
      • b.ValueChanged += ValueChangeDelegate(); + + DoSomeStuff(); +
      • b.Call(); + err??? <--------+ ValueChanged(); +
      • } + + } +
        +--------------------------------------------- +-------------------+

      Remember that the client and server are for all purposes are in two seperate application domains let alone two different processes let a lone two different machines. If you don't understand why marshalling events across seperate app domains is tricky then read on. :) The client is making a call b.Call which is remoted and marshalled correctly over to the server. If you don't do anything fancy, it is going to be syncronous and therefore block and wait for the response from the server. Over on the server, it is going to do the ObjectB.Call method when it makes an attempt to do the event. Okay, how does the server contact the client?? If you can't come up with a good answer then you see why events are a problem in Remoting. :) Neither application domain knows what state the other is in. Even if the client is making an asycronous remote call, the client would have to *stop* execution on whatever it is doing and do the event. The client side is either blocked waiting for a response or the client

      M 1 Reply Last reply
      0
      • T Tom Larsen

        Events conceptually are not sound in any network protocol. I'm surprised there was even an attempt in .Net Remoting to support this. The exception you are seeing is somewhat indicitive of the general problem. I wish that future versions of .Net Remoting would throw a more accurate exception than ArgumentException you often see in this case. Okay so what is the problem? Mechanically, it can't serialize the delegate and event cleanly across .Net Remoting. Seriously, how would .Net Remoting even begin to handle an delegates/events? Ignore the actual mechanical problems with serialization for a moment and look at the concept you are trying to do. Bare with my crude ascii art :)

        +--------------------------------------------+ +-------------------+

        • Client + + Server +
        •                                        +                  +                   +
          
        • ObjectA CallRemoteB() + ---------------->+ ObjectB Call() +
        • { + + { +
        • b.ValueChanged += ValueChangeDelegate(); + + DoSomeStuff(); +
        • b.Call(); + err??? <--------+ ValueChanged(); +
        • } + + } +
          +--------------------------------------------- +-------------------+

        Remember that the client and server are for all purposes are in two seperate application domains let alone two different processes let a lone two different machines. If you don't understand why marshalling events across seperate app domains is tricky then read on. :) The client is making a call b.Call which is remoted and marshalled correctly over to the server. If you don't do anything fancy, it is going to be syncronous and therefore block and wait for the response from the server. Over on the server, it is going to do the ObjectB.Call method when it makes an attempt to do the event. Okay, how does the server contact the client?? If you can't come up with a good answer then you see why events are a problem in Remoting. :) Neither application domain knows what state the other is in. Even if the client is making an asycronous remote call, the client would have to *stop* execution on whatever it is doing and do the event. The client side is either blocked waiting for a response or the client

        M Offline
        M Offline
        Mikke_x
        wrote on last edited by
        #3

        Hi! Thank you for you reply! I realize that what I was trying to do was not as easy or smart as I thought.. What puzzles me is that it works well if I use a delegate with only a string as a argument. Why does that work?? I cannot have a delegate with two strings as arguments, but one work. I tried to implement the ISerializable interface. That did not work either. I can buy the thought of the events not working if the server cannot find the client, that is reasonable. But why does it work if the argument is a string?? :confused: Best Regards Mikke

        T 1 Reply Last reply
        0
        • M Mikke_x

          Hi! Thank you for you reply! I realize that what I was trying to do was not as easy or smart as I thought.. What puzzles me is that it works well if I use a delegate with only a string as a argument. Why does that work?? I cannot have a delegate with two strings as arguments, but one work. I tried to implement the ISerializable interface. That did not work either. I can buy the thought of the events not working if the server cannot find the client, that is reasonable. But why does it work if the argument is a string?? :confused: Best Regards Mikke

          T Offline
          T Offline
          Tom Larsen
          wrote on last edited by
          #4

          Consider what is happening when you "sign up" for the event. You need to send a message to the server object to add ClientObject.ClientFunction to the delegate list. Assuming ClientObject is a MarshalByRefObject, it can marshal "itself" across. It can also marshal strings across. So technically it will succeed in making the functional call across the .Net Remoting. The problem is that it is meaningless to the server app domain because of all of the stuff I meantioned before. All of the object references only work in the client domain and will "blow up" if used in server domain. Oh yeah, I did mention a way to work around the limitation in .Net Remoting but it might not be clear without an example:

          ObjectA CallRemoteB()
          {
          /* old bad way
          b.ValueChanged += ValueChangeDelegate();
          b.Call();
          */
          // better way: sometime earlier the object signed up for the delegate like so
          // this.ValueChanged += new ValueChangedDelegate(this.onValueChanged());
          b.Call();
          if(this.ValueChanged != null)
          this.ValueChanged();
          }

          The event/delegate is now only in the client app domain so everything works.

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups