CSLA 2.0 Event Serialization w/ Windows Form and Remoting

CSLA 2.0 Event Serialization w/ Windows Form and Remoting

Old forum URL: forums.lhotka.net/forums/t/3391.aspx


jchau posted on Thursday, August 16, 2007

I am creating a clickonce windows application that uses remoting to perform operations on the server.  I have a simple DataHandler class that inherits CommandBase.  The DataPortal_Execute function performs a series of time consuming tasks and I want to notify the caller of some progress via an event called ProgressUpdate().  In my windows form, I attach an event handler to ProgressUpdate but that event never gets called.

Here's the code for my DataHandler class:

<Serializable()> _

Public Class DataHandler

Inherits CommandBase

Public Delegate Sub ProgressDelegate(ByVal aMessage As String)

<NonSerialized()> _

Private mNonSerializable As ProgressDelegate

Public Custom Event ProgressUpdate As ProgressDelegate

AddHandler(ByVal value As ProgressDelegate)

mNonSerializable = CType([Delegate].Combine(mNonSerializable, value), ProgressDelegate)

End AddHandler

RemoveHandler(ByVal value As ProgressDelegate)

mNonSerializable = CType([Delegate].Remove(mNonSerializable, value), ProgressDelegate)

End RemoveHandler

RaiseEvent(ByVal aMessage As String)

If mNonSerializable IsNot Nothing Then mNonSerializable(aMessage)

End RaiseEvent

End Event

Protected Overrides Sub DataPortal_Execute()

RaiseEvent ProgressUpdate("Starting...")

'do some task

RaiseEvent ProgressUpdate("Task1 finished.")

'do some task

RaiseEvent ProgressUpdate("Task2 finished.")

'cleanup

RaiseEvent ProgressUpdate("Finished successfully.")

End Sub

End Class

If I remove the 'NonSerialized()' attribute from the event, I get an error with dataportal trying to reference my windows form dll. 

 

RockfordLhotka replied on Tuesday, August 21, 2007

You need to do extra work to get callbacks to flow through remoting. An event is merely a method callback, so it has the same issue.

You should read Ingo Rammer's Remoting book for background, and you should be aware that there is no good solution here for complex networking environments. I believe I've answered questions about this on the forum in the past, so you may try doing some searches.

But...

  1. Your client must have a routable IP address - that is to say that the server MUST be able to "ping" the client
  2. You must configure your client as a remoting listener.
  3. You must create a MarshalByRefObject (MBRO) on the client
  4. You must pass a reference to your MBRO to the server along with your call - in your case probably as a field within the command object
  5. Calls on the MBRO on the server will then be routed to the actual object instance running on your client
  6. Keep in mind that the server calls will be on a background thread, so you MUST marshal the call from that background thread to your UI thread before trying to manipulate the UI in any way!

There are variations on this theme, but this is the basic structure of what needs to be done to do callbacks through remoting.

The killer is #1, because many client workstations aren't reachable from a server due to NAT or firewall issues. If that's the case, you are finished before you start; with one exception: there used to be some third-party remoting channels that did bi-directional TCP socket connections. If you can find one of them you can avoid most NAT/firewall routing issues.

Copyright (c) Marimer LLC