Geekpedia Programming Tutorials






Delegates and Events in C#

This C# tutorial will teach you how to create delegates and events in C# using a practical example of creating two applications, a client and a multi-threaded server. You will learn how to fire your own custom event from a class and handle it in a different class.

On Saturday, October 13th 2007 at 09:59 PM
By Andrew Pociu (View Profile)
*****   (Rated 4.9 with 19 votes)
Contextual Ads
More C# Resources
Advertisement
Download this Visual Studio 2005 project Download the Client Application project (Visual Studio 2005)

Download this Visual Studio 2005 project Download the Server Application project (Visual Studio 2005)


Event firing and handling

The scope of this tutorial is to teach you how to create your own events, fire them and handle them. If you done any C# programming you're sure to have used events already. The click of a button, the loading of the form, all these are events that are coded into the .NET Framework. However when you create your own classes, many times you'll find it necessary to create your own events. For taking full advantage of this tutorial it's best that you know at least the basics of object oriented programming in C#, such as classes, constructors, properties, instantiation, etc. Also if you know anything about working with threads, it will help.

In this tutorial we're going to create a real-life application, or at least the start of a real-life application. It will consist of two projects: a client and a server. The client application connects to the server application through TCP IP. These two applications could connect to each other through a network or through the Internet. As long as the port specified is the same in both applications (and the firewall doesn't block it), and if you specified the correct IP addresses, everything will work just fine. But where do the delegates and events come into play? In the server application. There we will have a class that listens for connections. When a client is accepted, we want an event to be fired. This event should be handled in the class that displays the form, so that we can show a message box.

Let's start by creating the client application, which has very little code to it.


The client application

Start Visual Studio 2005 and create a new C# Windows Application. I called mine "LilClient":

TCP Client Application

This is what our client application looks like. A TextBox and a Button btnConnect. The TextBox is named txtIp and it will store the IP address of the server that we want to connect to. Obviously this depends on where you'll run your server application. You could run it on the very same computer as the client application. However most important is that the IP address is the one of your machine, if you're going to run the client and the server on the same machine, or in a network, you should use the computer's network IP. Many times this is 192.168.0.1 however in my network it is 192.168.1.101. You can find the list of IP addresses that your computer uses by doing an ipconfig command at the MS-DOS command prompt.

First thing to do in this Windows Application is to add this using statement:


using System.Net.Sockets;



Double click the btnConnect button and you'll get to its Click event (speaking of events, eh!); inside add the following code:


private void btnConnect_Click(object sender, EventArgs e)

{

    // Create a new TCP client

    TcpClient tcpServer = new TcpClient();

    // Connect it to the specified IP address and port

    tcpServer.Connect(txtIp.Text, 1986);

    // Close the connection

    tcpServer.Close();

}



"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond"exception if the IP address you have entered is incorrect.
Next comes the server application where we're going to get into the real scope of this tutorial: delegates and custom events.


The server application

Start a new C# project. I gave mine a more serious name this time: "CustomEventsAndDelegates" - sounds classy, doesn't it?

Events and Delegates Server Application

The form is very similar to the one of the client: we have our txtIp TextBox, a btnStart Button and a lblStatus Label. Switch to code view and since we'll be using the IPAddress object in this class, add the following:


using System.Net;



Now double click the Start Server button to get to its Click event where you'll use the following code:


private void btnStart_Click(object sender, EventArgs e)

{

    // Parse the IP address from the textbox into an IPAddress object

    IPAddress ipAddr = IPAddress.Parse(txtIp.Text);

    // Create a new instance of the Monitor class and pass the IP address to the constructor

    Monitor myMonitor = new Monitor(ipAddr);

    // Bind the event to an event handler

    myMonitor.StatusChangedEvent += new StatusChangedHandler(myMonitor_StatusChanged);

    // Call the method that starts monitoring for connections

    myMonitor.StartMonitoring();

    // Let the user know

    lblStatus.Text = "Monitoring for connections...";

}



So what's happening here? First we simply create an IPAddress object where we store the IP address in the Text Box. Now I should tell you that the IP address in the TextBox is the IP address of the server, and since a server can have multiple network devices and IP addresses, we don't know which one should be used. Thus, the IP address should be typed in, or alternatively you can have the server application retrieve the list of IP addresses as shown in this tutorial I wrote a couple of years ago: http://www.geekpedia.com/tutorial149_Get-the-IP-address-in-a-Windows-application.html. The IP address should be the same one as the one that's entered in the client application.

What's the deal with the Monitor object? What namespace is that? Well that's the class we're going to create next. The main purpose of this class is to monitor for incoming connections from client applications. It will have a constructor that takes an IPAddress object, and that's why we pass the IP address to it when initializing the myMonitor object.

The next line is most interesting. That's where we bind the event that we're going to create very soon to an event handler. You can see that the event handler's name is myMonitor_StatusChanged, remember this because we're having a look at it in a second.

The last two lines are self explanatory: a method to start monitoring is called on the myMonitor object, and a label on the form is updated.

There's only one piece of code left in this class and that is the event handler:


public void myMonitor_StatusChanged(object sender, StatusChangedEventArgs e)

{

    MessageBox.Show("We got a call from the Monitor class:\r\n" + e.EventMessage, "Message From Server", MessageBoxButtons.OK, MessageBoxIcon.Information);

}



If you're not familiar with event handlers at all, you should know that this piece of code executes when we fire the event from a different class. If you looked at the Click events of various form objects such as buttons, this must be familiar to you. Only this time the handler is for our own custom event. And another interesting thing to note is that when this event fires, a parameter is passed to it through StatusChangedEventArgs e. This parameter will hold a message sent by the monitoring class, such as "A client has successfully connected!"


Creating and firing your own event

Now we're going to create our final code for this tutorial, but the most important. This is the code that monitors for connections, and when a client does connect, it will fire an event, event which we already handled in the main Form1 class.
In Visual Studio 2005 add a new class file: Monitor.cs. Add the following using statements since we'll be using networks & threads:


using System.Net;

using System.Net.Sockets;

using System.Threading;



This file will actually contain two classes. One is the Monitor class which we kept talking about but we never seem to get to :-) and the other is the StatusChangedEventArgs class that inherits EventArgs.

Since an event is really a delegate, we need to define a delegate with the signature that we want for the event. Might want to read that twice. For instance we want to pass some arguments - StatusChangedEventArgs, and the only place to define them is in the delegate's signature. So inside Monitor.cs and the namespace, but not inside the class, put the following line:


public delegate void StatusChangedHandler(object sender, StatusChangedEventArgs e);



Now that we know how the event will look like, thanks to the delegate signature, we need to define what arguments StatusChangedEventArgs will contain. First we need some way to set these arguments, because they're being passed useless if we don't set them to a value. And that's why we need a constructor. Of course, we also want to retrieve the arguments out of StatusChangedEventArgs so we need a property. All these will be defined into a class named StatusChangedEventArgs. you should put it in the Monitor.cs file:


public class StatusChangedEventArgs : EventArgs

{

    // This will store our only parameter / event argument, which is the event message

    private string EventMsg;

 

    // We need to define this property in order to retrieve the message in the event handler, back in Form1.cs

    public string EventMessage

    {

        get

        {

            return EventMsg;

        }

    }

 

    // The constructor will set the message

    public StatusChangedEventArgs(string strEventMsg)

    {

        EventMsg = strEventMsg;

    }

}



So we have the arguments defined, we can set and retrieve them. Inside Monitor.cs we should now deal with the Monitor class for which we created the file in the first place. And finally here it is, in all its glory, our Monitor class:


class Monitor

{

    // Will store the IP address passed to it

    IPAddress ipAddress;

 

    // The constructor sets the IP address to the one retrieved by the instantiating object

    public Monitor(IPAddress address)

    {

        ipAddress = address;

    }

 

    // Declare the event that we'll fire later

    public event StatusChangedHandler StatusChangedEvent;

    // The thread that will hold the connection listener

    private Thread thrListener;

    // The TCP object that listens for connections

    private TcpListener tlsServer;

    // The thread that will send information to the client

    private Thread thrSender;

    // Will tell the while loop to keep monitoring for connections

    bool ServRunning = false;

 

    public void StartMonitoring()

    {

        // Get the IP of the first network device, however this can prove unreliable on certain configurations

        IPAddress ipaLocal = ipAddress;

        if (tlsServer == null)

        {

            // Create the TCP listener object using the IP of the server and the specified port

            tlsServer = new TcpListener(ipaLocal, 1986);

        }

        // Start the TCP listener and listen for connections

        tlsServer.Start();

 

        // The while loop will check for true in this before checking for connections

        ServRunning = true;

 

        // Start the new tread that hosts the listener

        thrListener = new Thread(KeepListening);

        thrListener.Start();

    }

 

    private void KeepListening()

    {

        TcpClient tclServer;

        // While the server is running

        while (ServRunning == true)

        {

            // Accept a pending connection

            tclServer = tlsServer.AcceptTcpClient();

            // Start a new thread where our new client who just connected will be managed

            thrSender = new Thread(new ParameterizedThreadStart(AcceptClient));

            // The thread calls the AcceptClient() method

            thrSender.Start(tclServer);

        }

    }

 

    // Occures when a new client is accepted

    private void AcceptClient(object newClient)

    {

        // Set the argument/parameter to a message explaining what just happened

        StatusChangedEventArgs evArg = new StatusChangedEventArgs("A client was successfully accepted.");

        // Fire the event because a new client was accepted

        StatusChangedEvent(this, evArg);

    }

}


With the comments it's pretty much self explanatory. There's a method that starts the monitoring, one that does the listening, and finally one that accepts a client. Technically it doesn't do anything with the client connection, it just lets the main form know that a client has connected successfully, which was the main purpose of this tutorial all along.

Now that wasn't that hard, was it? If you run both applications and most importantly, input the correct IP addresses, you should get a message on the server application once you connect the client to it. And behind that, which looks like a very simple task to accomplish, you'll know that a lot of stuff really happens, an event defined by the signature of a delegate fires from a class, and with it carries the parameters defined in another class. The event is handled in the class that holds the form, which shows the message box. Here's the entire process:

Delegates and Events

P.S.: If when you run your client application you get an alert from the Windows Firewall or any other firewall for that matter, don't forget to unblock the application:

Windows Firewall
Digg Digg It!     Del.icio.us Del.icio.us     Reddit Reddit     StumbleUpon StumbleIt     Newsvine Newsvine     Furl Furl     BlinkList BlinkList

Rate Rate this tutorial
Comment Current Comments
by }{ombr3 on Monday, October 15th 2007 at 05:00 AM

Very good explanation, and simple to understand.

The only thing i miss is cache handling, because if you stop the application, the process is still running and it uses many MB of your RAM!

This tutorial could be a good basement for a simple multi-client chat application :)

by Andrei Pociu on Monday, October 15th 2007 at 09:06 AM

Actually our next tutorial is going to be a chat client and server application that is based on this code.

by }{ombr3 on Tuesday, October 16th 2007 at 03:30 AM

Yeah i\'m looking forward to this... sounds good :)

by Ahmed on Monday, December 24th 2007 at 12:42 PM

Thanks a lot but it doesn't work on the internet.
I think the connection is blocked by the router; I have tried it many times with different ports but each time I got a timeout exception.

I have tried to use IpAddress.Any for the server but it doesn't work either

Please help me I need to finish a sockets application in a couple of days but I'm stucked with this problem.

by Scott on Thursday, January 10th 2008 at 03:13 PM

This is pretty great!

How do you terminate the threads and or the connections at the end, though?

by Henri de Feraudy on Tuesday, January 22nd 2008 at 09:44 AM

I think it is weird to use the following code
TcpClient tcpServer = new TcpClient();
I mean the name of the variable is a bit dissonant.

by Snoop on Wednesday, April 23rd 2008 at 12:20 PM

Hi,
I need some help, i keep getting an exception, and it keeps pointing to the same place everytime,
tlsServer.Start();

What am i doing wrong?

by Pradeep Yadav on Friday, April 25th 2008 at 06:33 AM

This code is very helpful for me.
I was searching for such kind of helps anr codes.....


Thank you

by Hasini on Saturday, May 3rd 2008 at 01:33 PM

Hi,
Thank you for the helpful tutorial.
It worked perfectly when both the server and the client run in the same machine.
But I did not understand much how the server side methods work exactly.

by Lakshmi on Tuesday, July 22nd 2008 at 09:34 AM

HI,
thanks for the wonderful tutorial.
i needed one help.
In my chat application, the scenario is, when i ping the other person who is online on the same network, before getting my message he should get a notification saying "client1 wants to chat with you" with the accept button. and the chat winodw should open on the other side,only after clicking the accept button.

i'm just wondering if you could help me in this :)

thanks,

by Lakshmi on Tuesday, July 22nd 2008 at 09:34 AM

HI,
thanks for the wonderful tutorial.
i needed one help.
In my chat application, the scenario is, when i ping the other person who is online on the same network, before getting my message he should get a notification saying "client1 wants to chat with you" with the accept button. and the chat winodw should open on the other side,only after clicking the accept button.

i'm just wondering if you could help me in this :)

thanks,

by ylawan on Monday, August 11th 2008 at 09:39 AM

Hi Lakshmi,

Not sure but think what you need to do is to make each chat session behave both as a client and a server. As a client to be able ro request chat, and As a server to be able to listen and display message as you require.

Thanks Andrei Pociu for the tutorial.

Cheers

by Vijay on Wednesday, September 10th 2008 at 06:07 AM

Hi. Thanks and regards.

by J on Monday, September 15th 2008 at 01:32 PM

Where is the monitor class? The only one I can find is static in System.Threading;

by J on Monday, September 15th 2008 at 01:37 PM

Next time I'll read thru' more of the article ^^

by Dinesh Patankar on Friday, December 12th 2008 at 08:31 AM

Thanks for the wonderful tutorial....
Thanks and regards

by engkoment on Sunday, January 4th 2009 at 10:40 PM

yEh, this is what I need, for our thesis proposal.. thanks man..

but my application can also send files or documents, and I think its not that hard.

:)

by engkoment on Sunday, January 4th 2009 at 11:55 PM

also there must be installed MS .Net Framework Versions to run this application on computers that doesn't have one.

:)

by vrdude on Friday, January 23rd 2009 at 05:37 PM

When I download the server application project solution above, there are references to LogRecordEventArgs and RecordEventHandler that are not in the solution. Also the method AsyncLogEvent is the same name as the enclosing class.

by Abdullah on Sunday, February 1st 2009 at 10:39 PM

Thanks alot my friend
Abood!

by Paolo Meriggi on Thursday, April 16th 2009 at 05:29 PM

I found this tutorial simple and really useful. In a few cut'n'paste and some customization, I have been ready to deploy a brand new graphical component triggering events...

Thanks a lot

Paolo

by Jashim on Monday, April 20th 2009 at 07:04 AM

This is very usful tutorial and helpful. it did help me a lot since I am a new developer and new into c#,

thanks much.

by jitendra on Friday, July 3rd 2009 at 06:58 AM

yes this is very much useful to me thank buddy

by Cipher on Thursday, July 23rd 2009 at 04:09 PM

Just a note:

If you're running (or testing) this on only one machine (Client and Server on the same computer) its easier to use the IpAddress.LoopBack field in System.Net; namespace.

by Diego on Friday, July 24th 2009 at 08:10 PM

Hello... I was following your tut and got a problem, I'm actually using C# Express 2008... I have problems with the Monitor class... I included the System.Threading namespace on the code, and got the Monitor class recognized.. but, when I initialize it like this:
Monitor myMonitor = new Monitor(ipAddr);
I get an error: "Cannot create an instance of the abstract class or interface 'System.Threading.Monitor'"

I'm new to C#.. please if you can help me I would be very grateful.

Thanks!

by Diego on Sunday, July 26th 2009 at 01:30 PM

Sorry for being such an idiot! I didn't notice the Monitor class was below...
But... I don't get it to work either =S
In the line: tlsServer.Start();
I get this error: SocketException was unhandled.
I'm really new to this.. so please if someone can help me out... it would be great!!

by Shiv Kumar on Tuesday, July 28th 2009 at 06:51 AM

hello,

I have used this tutorial and it is great. easily understand. but i have a problem when i am trying to use it on internet.

the error comes........on the client side is...

help me to overcome this error... my emailid is shiv.knit@gmail.com

See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
at eventanddelegateforclient.Form1.butconnect_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message

by nERGYLFLAx on Wednesday, August 19th 2009 at 08:45 AM

Yo, I used this tutorial to create a chat server which is pretty ****ing sexy.

The only thing I want to figure out how to do with this code, is send messages to certain IPs excluding everyone else, and to be able to select those IPs. Any idea where I could find out how to do this? Email me @

af.nargalax@gmail.com

If you know how! THX

by Tristan on Monday, August 24th 2009 at 09:50 PM

I really understand why we use the delegate method because we use it for threading i like to make an audition game with threading it really helpful to make a arrow move

by kathirvel on Monday, August 31st 2009 at 03:37 AM

IPMSG
http://kathirvelmariappan.blogspot.com

by Turgon on Monday, October 12th 2009 at 05:04 PM

Hello mates..
I read this tutorial after reading your chat client one...
Both are excellent, straightforward, easy, and i got no bug at all!!
Thank you for your gr8 work, and looking forward for more of your tutorials :)

by Steven B on Friday, November 13th 2009 at 05:27 PM

Hello,

I am also getting the same error message when doing the Monitor class where when i type the full thing:
Monitor myMonitor = new Monitor(ipAddr);
I get an error: "Cannot create an instance of the abstract class or interface 'System.Threading.Monitor'"

and i am typing it right under:
IPAddress ipAddr = IPAddress.Parse(txtIp.Text);

so everything looks right as the example but still getting error message... why?

Thanks, if you can please post why or email it to me that would be great.

by jagadeesh on Thursday, November 19th 2009 at 05:13 AM

yes its really good...

my project is access control system

i have passive card and card reader when i show the card at front of machine it will accept and door open. its process.

but when i show the card the card details i want display my asp.net page so i get TCP/IP here problem is how to we fire event to tcp/ip for getting card details from machine i want source please help any one.........c# asp.net

by jagadeesh on Thursday, November 19th 2009 at 05:13 AM

yes its really good...

my project is access control system

i have passive card and card reader when i show the card at front of machine it will accept and door open. its process.

but when i show the card the card details i want display my asp.net page so i get TCP/IP here problem is how to we fire event to tcp/ip for getting card details from machine i want source please help any one.........c# asp.net

by Jasmine on Tuesday, February 9th 2010 at 01:14 AM

Hi.Gr8 code appln.It worked successfully.Thanks Man.You rock.

by sridevi on Thursday, March 11th 2010 at 03:56 AM

Nice one


Comment Comment on this tutorial
Name: Email:
Message:
Comment Related Tutorials
There are no related tutorials.

Comment Related Source Code
There is no related source code.

Jobs C# Job Search
My skills include:
Enter a City:

Select a State:


Advanced Search >>
Latest Tech Bargains

Advertisement

Free Magazine Subscriptions

Today's Pictures

Today's Video

Other Resources

Latest Download

Latest Icons