Click here to Skip to main content
12,887,473 members (31,644 online)
Click here to Skip to main content


266 bookmarked
Posted 19 Apr 2006

Two-way Remoting with Callbacks and Events, Explained

, 19 Jul 2006 CPOL
A demonstration of how separate applications on different machines are able to effectively communicate with one another.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels.Ipc;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

namespace RemotingServerClient
    public partial class fServer : Form
        public fServer()

            // Register a server channel on the Server where we 
            // will listen for clients who wish to communicate

            // Register callbacks to the static properties on the ServerTalk object
            ServerTalk.NewUser = new delUserInfo(NewUser);
            ServerTalk.ClientToHost = new delCommsInfo(ClientToHost);

            Thread t = new Thread(new ThreadStart(CheckClientToServerQueue));

        // The method that will be called when a new User registers.
        private void NewUser(string UserID)
            // since it originated from a different thread we need to marshal this back to the current UI thread.
            if (this.cboUsers.InvokeRequired)
                this.cboUsers.Invoke(new delUserInfo(NewUser), new object[] { UserID });
                this.cboUsers.Text = UserID;    // select the last added user

        // A loop invoked by a worker-thread which will monitor the static tread-safe ClientToServer 
        // Queue on the ServerTalk class and passes on any CommsInfo objects that are placed here.
        // If the variable _FormClosing turns true (when the form closes) it will stop the loop and
        // subsequently the life of the worker-thread.
        private bool _FormClosing = false;
        private void CheckClientToServerQueue()
            while (!_FormClosing)
                Thread.Sleep(50);   // allow rest of the system to continue whilst waiting...
                if (ServerTalk.ClientToServerQueue.Count > 0)
                    CommsInfo message = (CommsInfo)ServerTalk.ClientToServerQueue.Dequeue();

        private void fServer_FormClosing(object sender, FormClosingEventArgs e)
            _FormClosing = true;

        // A helper method that will marshal a CommsInfo from the client to 
        // our UI thread.
        private void ClientToHost(CommsInfo Info)
            // since it originated from a different thread we need to marshal this back to the current UI thread.
            if (this.txtFromClient.InvokeRequired)
                this.txtFromClient.Invoke(new delCommsInfo(ClientToHost), new object[] { Info });
                this.txtFromClient.Text = "From client: " + Info.Message + Environment.NewLine + this.txtFromClient.Text;

        private void RegisterChannel()
            // Set the TypeFilterLevel to Full since callbacks require additional security 
            // requirements
            SoapServerFormatterSinkProvider serverFormatter = new SoapServerFormatterSinkProvider();
            serverFormatter.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            // we have to change the name since we can't have two channels with the same name.
            Hashtable ht = new Hashtable();
            ht["name"] = "ServerChannel";
            ht["port"] = 9000;

            // now create and register our custom HttpChannel 
            HttpChannel channel = new HttpChannel(ht, null, serverFormatter);
            ChannelServices.RegisterChannel(channel, false);

            // register a WKO type in Singleton mode
            string identifier = "TalkIsGood";
            WellKnownObjectMode mode = WellKnownObjectMode.Singleton;

            WellKnownServiceTypeEntry entry = new WellKnownServiceTypeEntry(typeof(ServerTalk),
                identifier, mode);

        private void btnSend_Click(object sender, EventArgs e)
            if (cboUsers.Items.Count == 0)
                MessageBox.Show("No registered Users!", "No users");

            string UserID = cboUsers.Text;
            if (chkAll.Checked) UserID = "*";
            ServerTalk.RaiseHostToClient(UserID, this.txtToClient.Text);

            this.txtFromClient.Text = "To client " + UserID + ": " + this.txtToClient.Text + Environment.NewLine + this.txtFromClient.Text;



By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


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


About the Author

marcel heeremans
Software Developer (Senior)
United Kingdom United Kingdom
Ever since my dad bought me a Commodore 64 (some years back) I have been hooked to programming. For most of my working career I have worked intensely with C# (WinForms and WPF) but a few years back I started to investigate browser technologies and frameworks which are much more powerful than I thought at first!

I studied International Marketing but found the IT sector much more challenging. So straight from uni I took on some IT contract work in London in a buoyant market and never looked back.

If you wish to contact me then please do so on

You may also be interested in...

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170424.1 | Last Updated 19 Jul 2006
Article Copyright 2006 by marcel heeremans
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid