Microsoft & .NETVisual C#Asynchronous Programming in C#

Asynchronous Programming in C#

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Introduction

With visual studio 2012, now developers can use ‘await’ and ‘async’ keywords. Async/await methods are sequential in nature, but asynchronous when compiled and executed. The added benefit of using the ‘async’ keyword is that it provides a simpler way to perform potentially long-running operations without blocking the callers thread. The caller thread/method can continue its work without waiting for this asynchronous method to complete its job. This approach reduces additional code development effort. Each ‘async’ modifier/method should have at least one ‘await’.

‘Async’ and ‘Await’ Keywords

By using ‘async’ and ‘await’ keywords, you can use resources in the .NET Framework or the Windows Runtime to create an asynchronous method. The ‘await’ keyword is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. During this time, the control is returned back to the caller of this asynchronous method. Asynchrony proves especially valuable for applications that access the UI thread because all UI-related activity usually shares one thread. When you use asynchronous methods, the application continues to respond to the UI. You can resize or minimize a window or you can close the application if you don’t want to wait for it to finish.

In .NET Framework programming, an ‘async’ method returns a Task or a Task<TResult>. Inside an ‘async’ method, an ‘await’ operator is applied to a task that’s returned from a call to another ‘async’ method.

‘Async’ Return Types (C#)

The following return types are supported in ‘async’ call.

Void – If an ‘async’ method returns void, that means it can’t be awaited. It is a “fire and forget” mode, where the async method will run in parallel with the calling method.

Task You have to see it as Task<void>. If your method returns nothing, then the ‘async’ version should return Task so it will be awaitable.

Task<T> – If your method returns a type T, then the async version must return Task<T> to be awaitable.

Code Example of ‘Async’ and Await’

My first asynchronous example is a console application, in which I have created a method called the TimeconsumingProcess (), that will wait for 8000 milliseconds. The following code snippet should be self-explanatory.

Example #1

using System;
using System.ComponentModel;
using System.Threading.Tasks.
 
namespace Asyncprocessing
{
    public class  Asyncprocessing
    {
        static void Main()
        {
            InitializeComponent();
        }
 
        public static Task TimeconsumingProcess()
        {
            return Task.Run(() =>
            {
                System.Threading.Thread.Sleep(8000);
            });
        }
 
        public async void CallMyProcess()
        {
               await TimeconsumingProcess ();
            Console.WriteLine("Time Consuming Process end");
        }
 
        public  async void CallMe()
        {
             CallMyProcess ();
             Console.WriteLine ("Program execution completed");
        }      
    }
}

Example #2

In the following example we will use a file write operation asynchronous way using ‘async’ and ‘await’. In this example I have created an object of FileStream class, which has an option that causes asynchronous I/O to occur at the operating system level. Inheritance hierarchy of FileStream class is as follows…

Inheritance hierarchy of FileStream class
Inheritance hierarchy of FileStream class

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
 
using System.Collections.Generic;
using System.Threading.Tasks;
 
namespace AsyncFileOperation
{
class AsyncFileOperation
    {
      static void Main()                                    
      {
           WriteOperation();
      }
public async void WriteOperation()
{
    string myfilePath = @"tapas.txt";
    string mytext = "This is Tapas’s text filern";
 
    await WriteInTextFileAsync(myfilePath, mytext);
}
 
private async Task WriteInTextFileAsync (string myfilePath, string mytext)
{
    byte[] myencodedText = Encoding.Unicode.GetBytes(mytext);
 
    using (FileStream mysourceStream = new FileStream(myfilePath,
        FileMode.Append, FileAccess.Write, FileShare.None,
        bufferSize: 4096, useAsync: true))
    {
        await mysourceStream.WriteAsync(myencodedText, 0, myencodedText.Length);
    };
}
}
}
 

Example #3

In the following example I will demonstrate parallel processing of multiple text files. For each file, the WriteAsync method will return a task that is then added to a list of tasks. The await task will resume within the method when file processing is complete for all of the tasks. This program is an example of performance boost that we can achieve through asynchronous programming.

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
 
namespace ParallelAsyncFileOperation
{
class ParallelAsyncFileOperation
    {
      static void Main()                                 
      {
           WriteOperation();
      }
        public async void WriteOperation ()
        {
            Int filecounter = 20;
    string myfolder = @"Tapastempfolder";
    List<Task> mytasks = new List<Task>();
    List<FileStream> mysourceStreams = new List<FileStream>();
 
    try
    {
        for (int fileindex = 1; fileindex <= filecounter; fileindex++)
        {
  string myfiletext = "This is Tapas’s file No " + fileindex.ToString() +    
  "rn";
            string myfileName = "Tapasfile" + index.ToString("00") + ".txt";
            string myfilePath = myfolder + myfileName;
 
            byte[] myencodedText = Encoding.Unicode.GetBytes(mytext);
 
            FileStream mysourceStream = new FileStream(myfilePath,
                FileMode.Append, FileAccess.Write, FileShare.None,
                bufferSize: 4096, useAsync: true);
 
 Task theFileTask = mysourceStream.WriteAsync(encodedText, 0,  
 encodedText.Length);
                mysourceStreams.Add(sourceStream);
                tasks.Add(theTask);
        }
 
        await Task.WhenAll(tasks);
    }
 
    finally
    {
        foreach (FileStream mysourceStream in mysourceStreams)
        {
            mysourceStream.Close();
        }
    }
}
 
    }
}
 

Conclusions

The main advantage of asynchronous programming is, the task is performed in a different thread, so the main thread does not block till that task is completed. It is possible to execute other tasks by the time. It is better to use an asynchronous programming model in the case of long running tasks, so your application reacts to other user actions performed. Asynchronous improves responsiveness also. In an asynchronous process, the application can continue with other work that doesn’t depend on the other resource until the potentially blocking task finishes.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories