Click here to Skip to main content
12,302,330 members (43,224 online)
Click here to Skip to main content
Add your own
alternative version


84 bookmarked

A Remoting Event (Simple and Efficient for Enterprise Solutions)

, 21 Aug 2006 CPOL
Rate this:
Please Sign up or sign in to vote.
This article contains the simplest solutions for: the security problem for DelegateSerializationHolder, the IO problem, and the messaging speed problem. Note: Messaging speed problem will appear when your application has worked for a long time.

demo project Image


I always had an interest in socket programming. I have created several chat applications and complex socket based applications. When I learned about events in Remoting I was so glad, and the first thing that I thought about was creating a chat application. But in the test, I met with some problems.

Problem 1

The first problem was a security exception:

System.Security.SecurityException: Type System.DelegateSerializationHolder 
and the types derived from it (such as System.DelegateSerializationHolder) 
are not permitted to be deserialized at this security level.

Security Exception Image

Solution 1

This problem was solved by adding the typeFilterLevel attribute with Full value to the formatter element of both configuration files.

<formatter ref="soap" typeFilterLevel="Full" />

Problem 2

But again, it did not work and an IO exception occurred:

Exception has been thrown by the target of an invocation. ---> 
System.IO.FileNotFoundException: Could not load file or assembly 
'Client, Version=, Culture=neutral, PublicKeyToken=null' 
or one of its dependencies. The system cannot find the file specified.

This exception occurs while the request is deserialized at the server. The server tries to call the event handler whereas the event handler exists in the client assembly. Because the client assembly is not available at the server, the exception is thrown.

IO exception Image

Solution 2

An intermediate wrapper class, MarshalByRefObject will solve this problem. This wrapper class is located in the shared assembly, accessible for both the client and the server; therefore, a delegate can resolve the method's signature. In the client application, we will associate the shared object event with the WrapperMessageReceivedHandler method of the wrapper class and associate an event handler on the client with the MessageReceived event of the wrapper class.

Sequense of events Image

Why [OneWay] Attribute

Without defining the remote method as [OneWay], an exception will occur when the client is unreachable or has been disconnected without disassociating the event handler. By using [OneWay], no exception will occur on the client, but it will be in the invocation list of the server and, in longtime, will make your server slower to respond.

Solution 3

Instead of using the normal event invocation mechanism, you must invoke each delegate on your own, and if an exception occurs, you must disassociate the delegate from the invocation list of the event. In the end, you can remove the [OneWay] attribute.

Shared Class

/// <span class="code-SummaryComment"><summary></span>
/// Represents the method that will handle
/// the Remotable.RemoteClass.MessageReceived event.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="message">Received message</param></span>

public delegate void MessageHandler(string message);

/// <span class="code-SummaryComment"><summary></span>
/// Shared remoting class that orchestrate messaging tasks 
/// <span class="code-SummaryComment"></summary></span>

public class RemoteClass:MarshalByRefObject

    /// <span class="code-SummaryComment"><summary></span>
    /// Occurs when a broadcast message received.
    /// <span class="code-SummaryComment"></summary></span>

    public event MessageHandler MessageReceived;
    /// <span class="code-SummaryComment"><summary></span>
    /// Initializes a new instance of the Remotable.RemoteClass class.
    /// <span class="code-SummaryComment"></summary></span>

    public RemoteClass()

    /// <span class="code-SummaryComment"><summary></span>
    /// Obtains a lifetime service object to control the lifetime policy for this
    /// instance.
    /// <span class="code-SummaryComment"></summary></span>
    /// <span class="code-SummaryComment"><returns></span>
    ///An object of type 
    ///System.Runtime.Remoting.Lifetime.ILease used to control
    ///the lifetime policy for this instance. This is the current lifetime service
    ///object for this instance if one exists; otherwise, a new lifetime service
    ///object initialized to the value of the 
    ///null value means this object has to live forever.
    /// <span class="code-SummaryComment"></returns></span>

    public override object InitializeLifetimeService()
        return null;

    /// <span class="code-SummaryComment"><summary></span>
    /// Broadcast message to all clients
    /// <span class="code-SummaryComment"></summary></span>
    /// <span class="code-SummaryComment"><param name="message">message string</param></span>

    public void Send(string message)
        if (MessageReceived != null)
            MessageHandler messageDelegate = null;
            Delegate[] invocationList_ = null;
                invocationList_ = MessageReceived.GetInvocationList();
            catch (MemberAccessException ex)
                throw ex;
            if (invocationList_ != null)
                lock (this)
                    foreach (Delegate del in invocationList_)
                            messageDelegate = (MessageHandler)del;
                        catch (Exception e)
                            MessageReceived -= messageDelegate;

Client Application

RemoteClass remoteClass;
WrapperClass wrapperClass;

private void Form1_Load(object sender, EventArgs e)
    //Configure remoting.

    RemotingConfiguration.Configure(Application.StartupPath + 

    // Create a proxy from remote object.

    remoteClass = (RemoteClass)Activator.GetObject(typeof(RemoteClass), 
    //Create an instance of wrapper class.

    wrapperClass = new WrapperClass();
    //Associate remote object event with wrapper method.

    remoteClass.MessageReceived += new 
    //Associate wrapper event with current form event handler.

    wrapperClass.WrapperMessageReceived += new 

Wrapper Class

/// <span class="code-SummaryComment"><summary></span>
/// Occurs when a broadcast message received.
/// <span class="code-SummaryComment"></summary></span>

public event MessageHandler WrapperMessageReceived;
/// <span class="code-SummaryComment"><summary></span>
/// Wrapper method for sending message to the clients.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="sender">Caller object</param></span>
/// <span class="code-SummaryComment"><param name="args">Message data</param></span>

public void WrapperMessageReceivedHandler(string message)
    // forward the message to the client

    if(WrapperMessageReceived != null)


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Hossein Ghahvei Araghi
Program Manager System Group
Iran (Islamic Republic of) Iran (Islamic Republic of)
Hossein Ghahvei Araghi
Birth date: 1978
Birth place: Iran
Academic Credentials : BS(Tehran University)
Microsoft Credentials : MCP, MCAD, MCTS 2.0, MCTS 3.5, MCPD 2.0, MCPD 3.5

You may also be interested in...

Comments and Discussions

GeneralUsing Across a network Pin
mcstarSatx20-Sep-06 6:32
membermcstarSatx20-Sep-06 6:32 
GeneralRe: Using Across a network Pin
gio_ch28-Jul-11 7:25
membergio_ch28-Jul-11 7:25 
GeneralRe: Using Across a network Pin
Hossein Ghahvei Araghi30-Jul-11 21:07
memberHossein Ghahvei Araghi30-Jul-11 21:07 
GeneralRequested service not found Pin
Jeetu0075-Sep-06 14:38
memberJeetu0075-Sep-06 14:38 
GeneralRe: Requested service not found Pin
Jeetu00713-Sep-06 15:34
memberJeetu00713-Sep-06 15:34 
QuestionRe: Requested service not found Pin
camariei11-Dec-06 11:40
membercamariei11-Dec-06 11:40 
GeneralVB.Net Pin
FuSe51224-Aug-06 16:19
memberFuSe51224-Aug-06 16:19 
GeneralRe: VB.Net Pin
FuSe51224-Aug-06 16:58
memberFuSe51224-Aug-06 16:58 
Questionabout the NAT Pin
yonking23-Aug-06 22:41
memberyonking23-Aug-06 22:41 
AnswerRe: about the NAT Pin
shahrul6s20-Nov-07 21:37
membershahrul6s20-Nov-07 21:37 
GeneralRe: about the NAT Pin
gio_ch28-Jul-11 7:37
membergio_ch28-Jul-11 7:37 
GeneralMissing the point Pin
Alex_112-Aug-06 16:12
memberAlex_112-Aug-06 16:12 
GeneralRe: Missing the point Pin
Hossein eraghi16-Aug-06 0:33
memberHossein eraghi16-Aug-06 0:33 
GeneralRe: Missing the point Pin
Alex_119-Aug-06 21:24
memberAlex_119-Aug-06 21:24 

You still keep missing the point. Your

private void buttonSend_Click(object sender, EventArgs e)
ar = del.BeginInvoke(textBoxMessage.Text, null, null);

changes absolutelly nothing. The model you are using is wrong.
Your client sends the message to the server. Then the message is processed on the server and server sends the response back to the client and moves to the next client until the message is sent to every client. With current model the server can not send the message to the next client, if the response from the previous client is not received or delayed.

Total delay is

TotalDelay = NumberOfClients x ClientResponseTime

With 1 sec delay in each client(or the network) and 500 clients, total delay is 8.5 minutes. I am sure that your chat application is not supposed to run on the same computer with 500 clients on it.
If there is a problem (in the client or in the network), your system stops functioning, the next clients, after the broken one, do not receive the message at all. It is not how the server must work.

The real server works like that:
The client sends the message to the server and the server sends this message to all the clients at once.

Total delay is

TotalDelay = ClientResponseTime x 2

In this case total delay is less by 250 times (or about it). Broken client does not affect the next clients in the clients list.

Eraghi, you have to learn more. The system design is not just a coding, it is mostly the architecture of the system.

Regards, Alex

Welcome to the horrible world of “Enterprise” systems.

GeneralRe: It's just for you Pin
Hossein eraghi21-Aug-06 1:00
memberHossein eraghi21-Aug-06 1:00 
GeneralStill Missing the Point Pin
Alex_123-Aug-06 0:00
memberAlex_123-Aug-06 0:00 
GeneralInstructive points Pin
Hossein eraghi23-Aug-06 20:04
memberHossein eraghi23-Aug-06 20:04 
GeneralRe: Instructive points Pin
Alex_123-Aug-06 23:54
memberAlex_123-Aug-06 23:54 
GeneralAbout arrogance and professionalism Pin
Kfir.C12-Sep-07 1:41
memberKfir.C12-Sep-07 1:41 
QuestionWas anyone successful making work in v1.1 Pin
Bubba Ole10-Aug-06 5:50
memberBubba Ole10-Aug-06 5:50 
AnswerRe: Was anyone successful making work in v1.1 Pin
Hossein eraghi11-Aug-06 19:47
memberHossein eraghi11-Aug-06 19:47 
AnswerRe: Was anyone successful making work in v1.1 Pin
mihir250812-May-08 13:04
membermihir250812-May-08 13:04 
GeneralGood Pin
Obaid ur Rehman8-Aug-06 7:10
memberObaid ur Rehman8-Aug-06 7:10 
GeneralRe: Good Pin
Hossein eraghi8-Aug-06 21:44
memberHossein eraghi8-Aug-06 21:44 
GeneralSingleton versus SingleCall mode Pin
Henk van der Geld8-Aug-06 0:26
memberHenk van der Geld8-Aug-06 0:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160530.1 | Last Updated 21 Aug 2006
Article Copyright 2006 by Hossein Ghahvei Araghi
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid