[en] Return values for events (solved)

Topics: Technical Support
Jul 25, 2011 at 5:44 PM

Hello there,

I'm using your framework for over a month now and it works very well. Thank you for that.

But now I have another question concerning events. :-)

I want to use an event for informing the user that a file exists. The user should decide if to override it. So I created a new EventArgs class (that is serialized) to transport the needed information for the window. In order to receive the feedback from the user, this class has a boolean Override property that is written by the client. But when I access it from the server after the event has been fired, the value hasn't change.

I think that the return value is not transported to the server back. Is there any chance to get this return value? If not I would set the property in the published class but this is not the optimal way I think.

Alex

Coordinator
Jul 27, 2011 at 7:05 AM
Edited Jul 27, 2011 at 7:07 AM

Hi alexosoft,

the EventArgs object isn´t serialized back to server, because no call is made. This behavior ist by design and is common to all well-known RPC frameworks. Local events don´t have that problem, because event provider and event client are running inside the same process and share the same memory.

But there is a solution. In order to get your scenario to work, you must leave the EventArgs object on the server and pushing only a reference back to the client. The EventArgs class must inherit from MarshalByRef to support sending references across process boundaries. Have a look ate the following snippet:

public class RemotableEventArgs : MarshalByRefObject
{
    public bool Override { get; set; }

    public override InitializeLifetimeService() { return null; }
}

But this approach has some drawbacks:

  • The server side component, which provides the event must be stateful (this may decrease scalability)
  • If multiple clients handle the event, they may override their values each other (result cannot be correlated to a specific client; Last writer always wins)
  • You must write manual cleanup code to remove the RemotableEventArgs object from memory, if it is not needed anymore

Because of this arguments, I cannot recommend that solution. But I suggest another approach. Forget about the events and simply pass a callback delegate from client to the server method, which does your file stuff. This is very easy and has no of the above mentioned drawbacks.

// Server
public class FileStuffService : IFileStuffService
{
    public void StoreFileOnServer(byte[] fileData, string serverFileName, Func<string, bool> overrideCallback)
    {
        if (File.Exists(serverFileName) && overrideCallback!=null)
        {
            if (!overrideCallback(serverFileName))
                return; // Client cancelled the operation
        }
        File.WriteAllBytes(serverFileName, fileData)
    }
}

// Client
public class FileStuffClient : Form
{
    ...
   
    private void StoreFile()
    {
        byte[] fileData = File.ReadAllBytes(@"C:\test.txt");
        _proxy.StoreFileOnServer(fileData, @"C:\ServerFiles\test.txt", new Func<string, bool> ( this.ProcessFileOverrideRequest ));
    }

    private bool ProcessFileOverrideRequest(string serverFileName)
    {
        return MessageBox.Show(string.Format("Do you really want to override the file '{0}' on server?", serverFileName),"Question",MessageBoxButtons.OKCancel)==DialogResult.OK;
    }
}

Jul 27, 2011 at 11:06 AM

Hi Rainbird,

thank you very much for this help.

I implemented the safe way and worked directly. ;-)