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:
- 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.
- 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.
For a good example of Synchronous and Async calls, use .NET Reflector and look at the System.Net.Sockets.Socket namespace — the Connect and BeginConnect methods illustrate the method well.
Thanks for this article. I’m trying to wait for an async call to finish in the main UI thread using your appraoch, but couldn’t make it work. I can make your sample code work. However, once I replace the async function with my code, it stops working. The async function doesn’t execute. I guess the problem is that in my async function, I’m also doing UI update, which is blocked by Signal.WaitOne(). Can you please confirm if this is the problem? If so, do you have any solution? Thanks very much in advance.
@miliu: You adeptly answered your own question! If your async thread calls the main thread to perform a UI update, and your main thread is blocked waiting for the async thread to finish, then you have deadlock.
There is no technical way to break this deadlock. Your solution requires a redesign. Here are a couple suggestions:
If your async thread performs only a single UI update when it’s finished, then just pass back the necessary info to the main thread, terminate the async thread, the main thread will unblock, and then you can perform the UI update in the main thread.
If your async thread needs to perform multiple UI updates while the main thread is blocked, then you simply cannot block your main thread. You’ll have to allow your main thread to continue, and use some other technique such as a bool flag to indicate to the main thread whether the async thread has completed.
Thank you very much for the response. My UI updates are more than one (progress update), but your tip gives me some ideas.
Please check out following link for nice post
of Asynchronous ans Synchronous…
http://www.mindstick.com/Blog/178/Synchronous%20and%20asynchronous%20command%20execution%20in%20c%20net
Thanks to everyone for your nice article.
“Convert Between Synchronous and Asynchronous :
C# 411” ended up being a great blog post.
If solely there was alot more weblogs similar to this excellent one on
the world-wide-web. Anyhow, thank you for your personal precious time,
Laurence