When a program calls a synchronous function, the program halts and waits for the function to finish executing. When a program calls an asynchronous function, the program does not wait and continues to execute while the asynchronous function executes in the background.

By default, C# methods are synchronous. External functions that can take a long time to execute–such as interprocess communications (IPC) and database queries–are typically asynchronous. However, there may be instances where you need to make a synchronous function asynchronous and vice-versa.

To demonstrate, check out this simple C# console program:

using System;
using System.Threading;

namespace SyncAsync
{
    class Program
    {
        static void Main( string[] args )
        {
            Console.WriteLine( "Calling synchronous method:" );
            SyncMethod();
            Console.ReadLine();

            Console.WriteLine( "nCalling synchronous method asynchronously:" );
            SyncToAsync();
            Console.ReadLine();

            Console.WriteLine( "nCalling asynchronous method:" );
            AsyncMethod();
            Console.ReadLine();

            Console.WriteLine( "nCalling asynchronous method synchronously:" );
            AsyncToSync();
            Console.ReadLine();
        }

        static private void SyncMethod()
        {
            Console.WriteLine( "SyncMethod Begin" );
            for (int i = 1; i <= 3; i++)
            {
                Console.WriteLine( i );
                Thread.Sleep( 100 );
            }
            Console.WriteLine( "SyncMethod End" );
        }
        static private void SyncToAsync()
        {
            Console.WriteLine( "SyncToAsync Begin" );
            Thread thread = new Thread( new ThreadStart( SyncMethod ) );
            thread.Start();
            Console.WriteLine( "SyncToAsync End" );
        }

        private static Timer s_Timer;
        private static EventWaitHandle s_Signal;
        static private void AsyncMethod()
        {
            Console.WriteLine( "AsyncMethod Begin" );
            s_Timer = new Timer( AsyncExecute, null, 100, Timeout.Infinite );
            Console.WriteLine( "AsyncMethod End" );
        }
        static private void AsyncExecute( object state )
        {
            Console.WriteLine( "AsyncExecute Begin" );
            for (int i = 1; i <= 3; i++)
            {
                Console.WriteLine( i );
                Thread.Sleep( 100 );
            }
            Console.WriteLine( "AsyncExecute End" );
            AsyncCallback();
        }
        static private void AsyncCallback()
        {
            if (s_Signal != null)
                s_Signal.Set();
        }
        static private void AsyncToSync()
        {
            if (s_Signal == null)
                s_Signal = new EventWaitHandle( false, EventResetMode.ManualReset );
            Console.WriteLine( "AsyncToSync Begin" );
            AsyncMethod();
            s_Signal.WaitOne();
            Console.WriteLine( "AsyncToSync End" );
        }
    }
}

Convert Synchronous to Asynchronous

Functions should be made asynchronous if they may take a long time to complete, such as opening large files or connecting to remote computers. The typical way to make a synchronous function asynchronous is to execute the function in a separate thread.

In the sample program above, SyncMethod executes synchronously just like every other C# method, producing the following output:

Calling synchronous method:
SyncMethod Begin
1
2
3
SyncMethod End

The SyncToAsync method demonstrates how to make SyncMethod asynchronous by launching it in a separate thread, which produces the following output:

Calling synchronous method asynchronously:
SyncToAsync Begin
SyncToAsync End
SyncMethod Begin
1
2
3
SyncMethod End

Notice how SyncToAsync finishes and returns control to the program immediately, while SyncMethod executes asynchronously in the background.

Convert Asynchronous to Synchronous

Occasionally you may need to wait for an asynchronous function to complete. One of the easiest ways to do this is to use an EventWaitHandle, a System.Threading object that enables threads to communicate by signaling.

For simplicity in the sample program, AsyncMethod uses a timer to launch AsyncExecute, which executes asynchronously from the main program to produce the following output:

Calling asynchronous method:
AsyncMethod Begin
AsyncMethod End
AsyncExecute Begin
1
2
3
AsyncExecute End

Notice how AsyncMethod starts the timer and continues to execute, then the asynchronous AsyncExecute executes asynchronously. The AsyncExecute method simulates an external asynchronous function such as connecting to a remote database. When the asynchronous function finishes, it calls the AsyncCallback method.

To convert this asynchronous function to synchronous, use an EventWaitHandle:

  1. In the AsyncToSync method, create an EventWaitHandle object. After launching the asynchronous AsyncExecute, call the WaitOne method to halt program execution and wait for a signal to continue.
  2. In the AsyncCallback method, call the Set method on the EventWaitHandle object to signal the AsyncToSync method that the asynchronous function has completed.

The output will look like this:

Calling asynchronous method synchronously:
AsyncToSync Begin
AsyncMethod Begin
AsyncMethod End
AsyncExecute Begin
1
2
3
AsyncExecute End
AsyncToSync End

Notice how the AsyncToSync method waits for the asynchronous AsyncExecute method to complete before continuing, essentially making it synchronous.