1. Introduction to synchronous & Asynchronous Call
In this article, we will explore how one can use a delegate on the functions exposed by the remote objects. Also, we will see how do we call those remote object functions as synchronous and asynchronous. Basic knowledge on threading will help you catch this article in a better way but not a mandate. Below is a short note about synchronous and asynchronous function calls:
- When a function call is Synchronous, the client code that makes the call will wait for the completion of the call. Once the call returns it resumes executing the next statements exists after the call.
- When a function call is Asynchronous, the client function which makes the call will NOT wait for the completion of the called function. After calling the function, it soon starts executing the next statements.
2. About The Example
The Server in this example exposes a function which prints a running count by intentionally taking some time. One can think of this function as a long-running task on the Server.
The client is a Windows Form Application which has two buttons in it. One button is calling the remote function synchronously and other button does the same asynchronously. The client uses the delegate of the same type to make a call to the remote functions.
Our example has two running counts. One runs on the server and other one runs on the client application. The server displays the running count on the console window while client shows that in a text box. When we click the Start Sync button, the count will be running on the server and once it is finished, the count on the Windows Form starts. So, on this button click, the windows form will wait for the server to complete its counting before it starts its own counting. Here, we study how client makes Synchronous Remote Call to the server.
When we click the Start Async button, the count will run in parallel between a server and the calling client. This means, after the call the client will not wait for the server to complete its task. Here, we learn how the client can call same remote function Asynchronously. The below picture shows the application for this article:

Remoting Sync and Async Call – Example
3. Implementing Counter Remote Server
The code for the server is like this sites previous examples on Remoting. So you will not see much explanation here on the basics. If you need much explanation on the Remote Server, please have a look at the First Remoting article.
3.1 Namespace for Remoting
In the server, after creating the console project, we add a class called Counter and we derive it from
MarshalByRef
class. Then, we include the required name-space In the Counter.cs file. This Counter class will act as a Remote class.
1 2 |
//RemSrv 01: Include required assemblies using System.Runtime.Remoting; |
3.2 Counting Method of Remoting Server
The class has a constructor and a method ‘
PerformCount
’. This method is the Server’s Counting Task. We will call this counting from the client using delegates. Moreover, this is the method which we will call both Synchronous and Asynchronous way from the client. We will see about that when we are moving to the client-side coding. The code for this class is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//RemSrv 02: Initialize the remoting object public Counter() { Console.WriteLine("Remote Object Created. " + Environment.NewLine); } //RemSrv 03: Perform the counting operation. This //will take sometime and is useful to explain How //async call to this method is useful from //the client end. public void PerformCount() { int x; for (x = 1; x < 10000; x++) Console.WriteLine("Current Count : " + x.ToString()); Console.WriteLine("Counting is finished"); return; } |
3.3 Hosting Remote Server
In the application entry, we are hosting the remote object under the name ‘Counter’. For more detail look at the basic article given in the Remoting Section.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using System; using System.Collections.Generic; using System.Text; //RemSrv 04 : Required Assemblies using System.Runtime; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; namespace RemotingDelegate { class Program { static void Main(string[] args) { //RemSrv 05 : Create a communication channel (Server) //and register it TcpServerChannel SrvrChnl = new TcpServerChannel(13340); ChannelServices.RegisterChannel(SrvrChnl, false); //RemSrv 06 : Register the Remote Class so that the //Object can go and sit on the Remote pool RemotingConfiguration.RegisterWellKnownServiceType( typeof(RemotingDelegate.Counter), "Counter", WellKnownObjectMode.SingleCall); //RemSrv 07 : Halt the server so that Remote client can //access the object Console.WriteLine("Server is Running..."); Console.WriteLine("Press Any key to halt the Server"); Console.ReadKey(); } } } |
4. Implementing the Client
The client is a windows application and section 2 of this article explains each user interface elements in it.
4.1 Namespace Required for Remoting Client
We include the below name-spaces in the Form class to access the Remoting and Thread function called ‘Thread.Sleep’. Also note that the project reference for the server also included. Once the server and client build without error, one can split the exes into the server and client machines for testing purpose.
1 2 3 4 5 6 |
//Client 01: Include the required namespace using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using System.Threading; using RemotingDelegate; |
4.2 Delegate Declaration for Synchronous & Asynchronous Call
Once we are ready with the required name spaces, two delegates of the same are declared at the class level. One delegate is sufficient, but we kept two just to differentiate the way we will use it.
1 2 3 |
//Client 03: Declare delegates for Sync Call and Async Call public delegate void SyncCall(); public delegate void AsyncCall(); |
4.3 Counting Task of Remoting Client
The ‘
LocalCounter
’ function here does the same job of the ‘
PerformCount
’ function on the server. So, here we simulate that there are two long running tasks, one at the server side and the other one at the client side. This function helps us to understand behavior of Synchronous & Asynchronous Remote call in relation to the local long-running task in the client.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//Client 06: Start the Local Counter. Assume that //It is a long running task. private void LocalCounter() { long x; lblDisplay.Text = "Starting the Local Count..."; for (x = 1; x < 10000; x++) { txtCount.Text = x.ToString(); Application.DoEvents(); } lblDisplay.Text = "Local Count is Done."; } |
4.4 Calling Remote Function Synchronously
The click event handler for the button ‘Start Sync’ first creates the proxy for the remote object and stores that in a variable ‘
cntObj
’. Next, we create a delegate object of type
SyncCall
. We pass the function
PerformCount
to the delegate object by using the proxy ‘
cntObj
’. So,
SyncCall
delegate now points to the remote function
PerformCount
through the proxy here in the client. Once the delegate
fnCounter
is ready, we make a call to the remote function
PerformCount
using it. After this, a call to the local task (
LocalCounter
) also made. Note, the call made here is Synchronous. Below is the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private void btnSync_Click(object sender, EventArgs e) { //Client 02: Get the Proxy for remote object Counter cntObj = (Counter)Activator.GetObject( typeof(Counter), "tcp://localhost:13340/Counter"); //Client 04: Call the remote method through the //delegate. This call is Synchronous. SyncCall fnCounter = new SyncCall(cntObj.PerformCount); fnCounter(); //Client 05: Call the Local Counter LocalCounter(); } |
Note that after making a call to the remote object using the delegate, the execution will pause at line 11 till the remote function finishes its task. Means, the LocalCounter call will wait for the Server to complete. Once the task is completed on the server, the execution resumes here on the client and calls the function LocalCounter. One can observe this by running the sample. First the console window on the server displays the running count. Once server completes its counting task, one can see the counter on the client form starts. The text box in the windows form renders this running count.
4.5 Delegate for Asynchronous Call
For making the asynchronous call, we create the delegate in the same way as we did in the previous step. But this time the delegate type is
AsyncCall
. Below is the code:
1 2 3 4 5 6 7 |
//Client 07: Create the proxy for remote Object and //set the delegate to the required remote function. Counter cntObj = (Counter)Activator.GetObject( typeof(Counter), "tcp://localhost:13340/Counter"); AsyncCall FnCounter = new AsyncCall( cntObj.PerformCount); |
4.6 BeginInvoke Function and IAsyncResult Type
Once we create the delegate, instead of calling the function directly through it as we did before, we are using the
BeginInvoke
method on the delegate. The first parameter is a callback. On completion of task, the called remote function report back to the caller through this callback. As we are dealing with remoting, this is not covered here to avoid complexity. But this callback is handy for Non-Distributed applications. So, we are passing null for both the parameters. We store the return value in the
IAsyncResult
. This is to do a check on the Server operation to make a safe call on the
EndInvoke
.
1 2 3 |
//Client 08: Call the remote method through the //delegate. This is an Asynchronous call. IAsyncResult AR = FnCounter.BeginInvoke(null , null); |
4.7 Server Task and Client Task Running Asynchronously
After the above call, we are making a call to the local task. Here, the client after making a call to the
PerfomCount
using the
BeginInvoke
method on the delegate, immediately moves to the next statement. The next statement is a function-call for counting on the windows form. Unlike Synchronous call in Section 4.5, the client does not wait for the server to finish its counting.
1 2 3 |
//Client 09: Call the Local Counter. The Local Counter // also run in parallel. LocalCounter(); |
4.8 Client Waiting for Server Task – IsCompleted of IAsyncResult
Finally, after making the call to both the client & server counting function to run simultaneously, we are waiting at the end of the routine to make a call to the
EndInvoke
. Note, this is a pair of its corresponding BeginInvoke. Remember, when we called the BeginInvoke function we stored the return value of type
IAsyncResult
in a reference called
AR
. Now, we use the
IsCompleted
Property of it to test the completion of the server’s task. Once we know the server is done with its task, we can make a call to EndInvoke safely by passing the instance of type
IAsyncResult
.
1 2 3 4 5 |
//Client 10: Test the Remote counting is finsihed or Not //before invoking the EndInvoke method on the delegate while (!AR.IsCompleted) Thread.Sleep(500); FnCounter.EndInvoke(AR); |
The entire event Handling routine for the ‘Start Async’ button is shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
private void btnAsync_Click(object sender, EventArgs e) { //Client 07: Create the proxy for remote Object and //set the delegate to the required remote function. Counter cntObj = (Counter)Activator.GetObject( typeof(Counter), "tcp://localhost:13340/Counter"); AsyncCall FnCounter = new AsyncCall( cntObj.PerformCount); //Client 08: Call the remote method through the //delegate. This is an Asynchronous call. IAsyncResult AR = FnCounter.BeginInvoke(null , null); //Client 09: Call the Local Counter. The Local Counter // also run in parallel. LocalCounter(); //Client 10: Test the Remote counting is finsihed or Not //before invoking the EndInvoke method on the delegate while (!AR.IsCompleted) Thread.Sleep(500); FnCounter.EndInvoke(AR); } |
5. Screenshot of Synchronous and Asynchronous Call
In synchronous call, the Server runs its counter while client waits. In the console window one can see the running counts. After this count, one can see the count running on the client text box.

Dotnet Remoting Delegate called in synchronous way
In asynchronous call, the client does not wait for the server to complete its task. So we will see counter running on the Server and Client simultaneously. One can observe this by looking at the running count in the console window and the text box of the client form. The below screen-shot explains this:

Dotnet Remoting Delegate called in Asynchronous way
Source Code: Download Example From Google Drive
Categories: Remoting
Tags: C# BeginInvoke, C# EndInvoke, C# IAsyncResult, IAsyncResult IsCompleted