Asynchronous programming with async, await, Task in C#

C# and .NET Framework (4.5 & Core) supports asynchronous programming using some native functions, classes, and reserved keywords.

Before we see what is asynchronous programming, let's understand what is synchronous programming using the following console example.

In the above example, the LongProcess() method is some long-running task such as reading a file from the server, calling a web API that returns a large amount of data or uploading or downloading a big file. It takes a little longer time to execute ( Thread.Sleep(4000) holds it for 4 seconds just to show long execution time). The ShortProcess() is a simple method that gets executed after the LongProcess() method.

The above program executes synchronously. It means execution starts from the Main() method wherein it first executes the LongProcess() method and then ShortProcess() method. During the execution, an application gets blocked and becomes unresponsive (You can see this in Windows-based applications mainly). This is called synchronous programming where execution does not go to next line until the current line executed completely.

What is Asynchronous Programming?

In asynchronous programming, the code gets executed in a thread without having to wait for an I/O-bound or long-running task to finish. For example, in the asynchronous programming model, the LongProcess() method will be executed in a separate thread from the thread pool, and the main application thread will continue to execute the next statement.

Microsoft recommends Task-based Asynchronous Pattern  to implement asynchronous programming in the .NET Framework or .NET Core applications using async , await keywords and Task or Task<TResult> class.

Now let's rewrite the above example in asynchronous pattern using async keyword.

In the above example, the Main() method is marked by the async keyword, and the return type is Task . The async keyword marks the method as asynchronous. Note that all the methods in the method chain must be async in order to implement asynchronous programming. So, the Main() method must be async to make child methods asynchronous.

The LongProcess() method is also marked with the async keyword which makes it asynchronous. The await Task.Delay(4000); holds the thread execute for 4 seconds.

Now, the program starts executing from the async Main() method in the main application thread. The async LongProcess() method gets executed in a separate thread and the main application thread continues execution of the next statement which calls ShortProcess() method and does not wait for the LongProcess() to complete.

async, await, and Task

Use async along with await and Task if the async method returns a value back to the calling code. We used only the async keyword in the above program to demonstrate the simple asynchronous void method.

The await keyword waits for the async method until it returns a value. So the main application thread stops there until it receives a return value.

The Task class represents an asynchronous operation and Task<TResult> generic class represents an operation that can return a value. In the above example, we used await Task.Delay(4000) that started async operation that sleeps for 4 seconds and await holds a thread until 4 seconds.

The following demonstrates the async method that returns a value.

In the above example, in the static async Task<int> LongProcess() method, Task<int> is used to indicate the return value type int. int val = await result; will stop the main thread there until it gets the return value populated in the result. Once get the value in the result variable, it then automatically assigns an integer to val .

An async method should return void ,  Task , or  Task<TResult> , where TResult is the return type of the async method. Returning void is normally used for event handlers. The async keyword allows us to use the await keyword within the method so that we can wait for the asynchronous method to complete for other methods which are dependent on the return value.

If you have multiple async methods that return the values then you can use await for all methods just before you want to use the return value in further steps.

In the above program, we do await result1 and await result2 just before we need to pass the return value to another method.

Thus, you can use async , await, and Task to implement asynchronous programming in .NET Framework or .NET Core using C#.

  • How to get the sizeof a datatype in C#?
  • Difference between String and StringBuilder in C#
  • Static vs Singleton in C#
  • Difference between == and Equals() Method in C#
  • How to loop through an enum in C#?
  • Generate Random Numbers in C#
  • Difference between Two Dates in C#
  • Convert int to enum in C#
  • BigInteger Data Type in C#
  • Convert String to Enum in C#
  • Convert an Object to JSON in C#
  • Convert JSON String to Object in C#
  • DateTime Formats in C#
  • How to convert date object to string in C#?
  • Compare strings in C#
  • How to count elements in C# array?
  • Difference between String and string in C#.
  • How to get a comma separated string from an array in C#?
  • Boxing and Unboxing in C#
  • How to convert string to int in C#?

how to write task void in c#

We are a team of passionate developers, educators, and technology enthusiasts who, with their combined expertise and experience, create in-depth, comprehensive, and easy to understand tutorials. We focus on a blend of theoretical explanations and practical examples to encourages hands-on learning. Learn more about us

  • Entrepreneur
  • Productivity

Dot Net Tutorials

Back to: C#.NET Tutorials For Beginners and Professionals

Task in C# with Examples

In this article, I am going to discuss Task in C# with Examples. Please read our previous article where we discussed how to implement Asynchronous Programming using Async and Await Operators in C# with Examples.

In C#, when we have an asynchronous method, in general, we want to return one of the following data types.

  • Task and Task<T>
  • ValueTask and ValueTask<T>

We will talk about ValueTask later, Now let us keep the focus on Task. The Task data type represents an asynchronous operation. A task is basically a “promise” that the operation to be performed will not necessarily be completed immediately, but that it will be completed in the future.

What is the difference between Task and Task<T> in C#?

Although we use both of them i.e. Task and Task<T> in C# for the return data type of an asynchronous method, the difference is that the Task is for methods that do not return a value while the Task<T> is for methods that do return a value of type T where T can be of any data type, such as a string, an integer, and a class, etc. We know from basic C# that a method that does not return a value is marked with a void. This is something to avoid in asynchronous methods. So, don’t use async void except for event handlers.

Example to Understand Task in C#:

In our previous example, we have written the following SomeMethod.

Now, what we will do is we will move the Task.Dealy to separate method and call that method inside the SomeMethod. So, let’s create a method with the name Wait as follows. Here, we mark the method as async so it is an asynchronous method that will not block the currently executing thread. And when calling this method it will wait for 10 seconds. And more importantly, here we use the return type as Task as this method is not going to return anything.

In asynchronous programming when your method does not return anything, then instead of using void you can use Task. Now, from the SomeMethod we need to call the Wait method. If we call the Wait method like the below then we will get a warning.

Here, you can see green lines under the Wait method as shown in the below image.

Task in C# with Examples

Why is that?

This is because the Wait method returns a Task and because it does return a Task, then it means that this will be a promise. So, this warning of the Wait method informed us that, if we don’t use the await operator while calling the Wait method, the Wait method is not going to wait for this operation to finish, which means that once we call the Wait method, the next line of code inside the SomeMethod is going to be executed immediately. Let us see that practically. The following is the complete example code.

Output: Once you execute the above code, then you will observe that without any delay we are getting the output as shown in the below image. This is because we are not using the await operator while calling the Wait method and hence it will not wait for the Wait method to complete. After 10 seconds the print statement within the Wait method is printed.

What is the difference between Task and Task<T> in C#?

In the above example, we use await Task.Delay inside the Wait method. This will suspend the thread for this Wait method execution only. It will not suspend the thread for SomeMethod execution. Now, let’s see what happens when we use the await operator as shown in the below example.

First thing, once you put the await operator, as shown above, the green warning will be gone. With await operator we are saying, please wait for this Wait method execution to finish before executing the next line of code inside the SomeMethod. That means it will not execute the last print statement inside the SomeMethod until the Wait method completes its execution.

await operator in C#

So, let us see that. The complete example code is given below

Example to Understand Task in C#

Now, you can observe in the above output that once it calls the Wait method, then the SomeMethod will wait for the Wait method to complete its execution. You can see that before printing the last print statement of the SomeMethod, it prints the printing statement of the Wait method. Hence, it proves that when we use await operator then the current method execution waits until the called async method completes its execution. Once the async method, in our example Wait method, complete its example, then the calling method, in our example SomeMethod, will continue its execution i.e. it will execute the statement which is present after the async method call.

What if you don’t want to wait for an asynchronous method in C#?

If you don’t want your method execution to wait for the asynchronous method to complete its execution, then, in that case, you need to use the return type of the asynchronous method to void. For a better understanding, please have a look at the below example. In the below example, we have used void as the return type of the asynchronous Wait method and while calling the asynchronous Wait method inside the SomeMethod we are not using await operator. This time please observe we are not getting any warning.

What if you don’t want to wait for an asynchronous method in C#?

Now you can observe the first four statements are printed immediately without waiting for the Wait method. After 10 seconds only the last statement is printed on the console window. Now, I hope you understand when to use Task and when to use void as the return type of an asynchronous method. I hope you also understand the importance of await operator.

Here, we have seen the examples of the async method without returning any value and hence we can use either void or Task as per our requirement. But what if the async method returns a value? If the async method returns a value then we need to use Task<T> and which we will discuss in our next article.

In the next article, I am going to discuss How to Return a Value from a Task in C# with Examples. Here, in this article, I try to explain Task in C# with Examples. I hope you enjoy this Task C# with Examples article.

dotnettutorials 1280x720

About the Author: Pranaya Rout

Pranaya Rout has published more than 3,000 articles in his 11-year career. Pranaya Rout has very good experience with Microsoft Technologies, Including C#, VB, ASP.NET MVC, ASP.NET Web API, EF, EF Core, ADO.NET, LINQ, SQL Server, MYSQL, Oracle, ASP.NET Core, Cloud Computing, Microservices, Design Patterns and still learning new technologies.

7 thoughts on “Task in C#”

how to write task void in c#

Guys, Please give your valuable feedback. And also, give your suggestions about this Task in C# concept. If you have any better examples, you can also put them in the comment section. If you have any key points related to Task in C#, you can also share the same.

how to write task void in c#

what is the difference of async and Task

how to write task void in c#

Simply Awesome. Very nice explanation…I am looking for more content in this site. Keep up doing good work.

how to write task void in c#

Don’t show videos ads . It’s ruining the site. And it’s very irritating as well.

Thanks we take into this consideration and disable the video ads.

how to write task void in c#

hi, thanks for this very good tutorial, truly a step by step and clear run through, i went over a good few articles and left more puzzled after each one, until I read yours. Exactly how code should be explained.

how to write task void in c#

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Blog about Microsoft technologies (.NET, ASP.NET Core, Blazor, EF Core, WPF, TypeScript, etc.)

Awaiting an async void method in .NET

how to write task void in c#

# Additional Resources

How-To Geek

How do tasks work in c# async/background threads.

If you want to make web requests in C#, or just want to do some background processing, you'll need to use asynchronous background tasks to not block up the main thread.

Quick Links

What is async/await, what are tasks.

If you want to make web requests in C#, or just want to do some background processing, you'll need to use asynchronous background tasks to not block up the main thread. We'll discuss what they are, and how to use them.

To use Tasks, you must first understand the concept of async / await . C# tasks don't have to run asynchronously, but considering the sole purpose of them is to represent an asynchronous operation, they almost always will run async. You don't want to run operations like fetching web requests and writing to hard drives on the main thread, because it would hold up the rest of the application (including the UI) while waiting for the result.

async / await  is special syntax used to deal with asynchronous operations. If a function is marked as async , it will usually return a Task, except in cases of event handlers that return void .

Inside the async function, you can use the  await  keyword to wait for async operations to finish without blocking the whole thread. Everything that comes after the await  keyword will only run after the

 operation finishes.

public async Task FetchWebResponse(string url)

var response = await SendRequest(url)

The value being awaited must be a Task, as the two go hand in hand with each other. When you call the SendRequest()  function, it returns a Task<T> , and the program waits until that task finishes. You can think of await  as a keyword used to return or wait for the value of a task to finish.

Tasks are wrappers used to deal with asynchronous functions. They essentially represent a value that will be returned in the future. You can use the await  keyword to wait for the result, or access it directly by checking if Task.IsCompleted  and then reading the value of Task.Result .

You can create them by writing an async function with a return type of Task<T> . Then, all you have to do is return a value of type T, and .NET will interpret that as returning a Task. You can use await  inside this task to wait for async operations, which in turn return a task themselves.

You can start running a Task using Task.Run(Action action) . This will queue up the Task on the thread pool, which will run in the background on a different thread. The thread pool takes a queue of tasks, and assigns them to CPU threads for processing. Once they return, they're put into the list of completed tasks where their values can be accessed.

However, even though it's on a background thread, it's still very important to use async/await . If you make a blocking call to an API on a background thread, and don't await  it, .NET will keep that thread blocked until it completes, filling up the thread pool with useless threads doing nothing but hurting performance.

If you need to await a task from the UI thread, start it with Task.Run , then check regularly to see if the task has been completed. If it has, you can handle the value.

You can also run and await tasks inside other Tasks. For example, say you have a function inside a task, DoExpensiveCalculation() , that takes a while to execute. Rather than processing it synchronously, you can write it as a Task, and queue up a background thread at the beginning of the main task. Then, when you need the value from that calculation, you can simply await  the task, and it will yield until the task is completed, and the return value is returned.

Async in C# 5.0 by Alex Davies

Get full access to Async in C# 5.0 and 60K+ other titles, with a free 10-day trial of O'Reilly.

There are also live events, courses curated by job role, and more.

Chapter 4. Writing Async Methods

Now we know how great asynchronous code is, but how hard it is to write? It’s time to look at the C# 5.0 async feature. As we saw previously in What Async Does , a method marked async is allowed to contain the await keyword.

The await expression in this example transforms the method, so it pauses during the download, then resumes when the download is done. This transformation makes the method asynchronous. In this chapter, we’ll explore writing async methods like this one.

Converting the Favicon Example to Async

We’ll now modify the favicon browser example from earlier to make use of async. If you can, open the original version of the example (the default branch) and try to convert it by adding async and await keywords before reading any further.

The important method is AddAFavicon , which downloads the icon, then adds it to the UI. We want to make this method asynchronous, so that the UI thread is free to respond to user actions during the download. The first step is to add the async keyword to the method. It appears in the method signature in the same way that the static keyword does.

Then, we need to wait for the download using the await keyword. In terms of C# syntax, await acts as a unary operator, like the ! not operator, or the ( type ) cast operator. It is placed to the left of an expression and means to wait for that expression asynchronously.

Finally, the call to DownloadData must be changed to instead call the asynchronous version, DownloadDataTaskAsync .

An async method isn’t automatically asynchronous. Async methods just make it easier to consume other asynchronous methods. They start running synchronously, until they call an asynchronous method and await it. When they do so, they necessarily become asynchronous themselves. Sometimes, an async method never awaits anything, in which case it runs synchronously.

Compare this to the other two versions of this code we’ve looked at. It looks much more like the original synchronous version of the code. There’s no extra method, just a little extra code in the same structure. However, it behaves much more like the asynchronous version that we wrote in Converting the Example to Use Manual Asynchronous Code .

Task and await

Let’s break down the await expression we’ve written. Here is the signature of the WebClient.DownloadStringTaskAsync method:

The return type is Task<string> . As I said in An Introduction to Task , a Task represents an ongoing operation, and its subclass Task< T > represents an operation that will have a result of type T at some point in the future. You can think of Task< T > as a promise of a T when the long-running operation completes.

Task and Task< T > can both represent asynchronous operations, and both have the ability to call back your code when the operation is done. To use that ability manually, you use their ContinueWith methods to pass a delegate containing the code to execute when the long-running operation is done. await uses the same ability to execute the rest of your async method in the same way.

If you apply await to a Task< T > , it becomes an await expression , and the whole expression has type T . That means you can assign the result of awaiting to a variable and use it in the rest of the method, as we’ve seen in the examples. However, when you await a non-generic Task , it becomes an await statement , and can’t be assigned to anything, just like a call to a void method. This makes sense, as a Task doesn’t promise a result value, it only represents the operation itself.

There is nothing stopping us from splitting up the await expression, so we can access the Task directly, or do something else, before awaiting it.

It is important to fully understand the implications of this. The method DownloadStringTaskAsync is executed on the first line. It begins executing synchronously, in the current thread, and once it has started the download, it returns a Task<string> , still in the current thread. It’s only later when we await that Task<string> that the compiler does something special. This is all still true if you write the await on the same line as the call to the asynchronous method.

The long-running operation starts as soon as the call to DownloadStringTaskAsync is made, which gives us a very simple way to perform multiple asynchronous operations concurrently. We can just start multiple operations, keeping all the Task s, then await them all afterwards.

This is a dangerous way to await multiple Task s, if they may throw exceptions. If both operations throw an exception, the first await will propagate its exception, which means secondTask is never awaited. Its exception will not be observed, and depending on .NET version and settings, may be lost or even rethrown on an unexpected thread, terminating the process. We’ll see better ways to do this in Chapter 7 .

Async Method Return Types

There are three return types that a method marked async may have:

Task< T > for some type T

No other return type is allowed because async methods in general aren’t finished when they return. Typically, an async method will await a long-running operation, which means that the method returns quickly, but will resume in the future. That means no sensible result value is available when the method returns. The result will be available later.

I’ll make the distinction between the return type of a method—for example, Task<string> —and the result type that the programmer actually intends to give to the caller, which in this case is string . In normal non-async methods, the return type and the result type are always the same, but the difference is important for async methods.

It’s obvious that void is a reasonable choice of return type in an asynchronous situation. A async void method is a “fire and forget” asynchronous operation. The caller can never wait for any result, and can’t know when the operation completes or whether it was successful. You should use void when you know that no caller will ever need to know when the operation is finished or whether it succeeded. In practice, this means that void is used very rarely. The most common use of async void methods is in the boundary between async code and other code, for example a UI event handler must return void .

Async methods that return Task allow the caller to wait for the operation to finish, and propagate any exception that happened during the asynchronous operation. When no result value is needed, an async Task method is better than an async void method because it allows the caller to also use await to wait for it, making ordering and exception handling easier.

Finally, async methods that return Task< T > , for example Task<string> , are used when the asynchronous operation has a result value.

Async, Method Signatures, and Interfaces

The async keyword appears in the declaration of a method, just like the public or static keywords do. Despite that, async is not part of the signature of the method, in terms of overriding other methods, implementing interfaces, or being called.

The only effect that the async keyword has is on the compilation of the method to which it is applied, unlike the other keywords that are applied to a method, which change how it interacts with the outside world. Because of this, the rules around overriding methods and implementing interfaces completely ignore the async keyword.

Interfaces can’t use async in a method declaration, simply because there is no need. If an interface requires that a method returns Task , the implementation may choose to use async , but whether it does or not is a choice for the implementing method. The interface doesn’t need to specify whether to use async or not.

The return Statement in Async Methods

The return statement has different behavior in an async method. Remember that in a normal non-async method, use of the return statement depends on the return type of the method:

return statements must just be return; , and are optional

return must have an expression of type T (for example return 5+x; ) and must exist at the end of the method on all code paths

In a method marked async , the rules apply in different situations:

return statements must just be return; and are optional

return must have an expression of type T and must exist at the end of the method on all code paths

In async methods, the return type of the method is different from the type of the expression found in the return statement. The compiler transformation can be thought to wrap up the value you return in a Task< T > before giving it to the caller. Of course, in reality, the Task< T > is created immediately, and only filled with your result value later, once any long-running operation is done.

Async Methods Are Contagious

As we’ve seen, the best way to consume a Task returned by an asynchronous API is to await it in an async method. When you do this, your method will typically return Task as well. To get the benefit of the asynchronous style, the code that calls your method must not block waiting for your Task to complete, and so your caller will probably also await you.

Here’s an example of a helper method I’ve written that gets the number of characters on a web page, and returns them asynchronously.

To use it, I need to write another async method, which returns its result asynchronously as well:

In this way, we end up writing chains of async methods, each awaiting the next. Async is a contagious programming model, and it can easily pervade a whole codebase. But I think that because async methods are so easy to write, this isn’t a problem at all.

Async Anonymous Delegates and Lambdas

Ordinary named methods can be async, and the two forms of anonymous methods can equally be async. The syntax is very much like normal methods. Here is how to make an asynchronous anonymous delegate:

And here is an async lambda:

All the same rules apply in these as in ordinary async methods. You can use them to keep code concise, and to capture closures, in exactly the same way you would in non-async code.

Get Async in C# 5.0 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.

Don’t leave empty-handed

Get Mark Richards’s Software Architecture Patterns ebook to better understand how to design components—and how they should interact.

It’s yours, free.

Cover of Software Architecture Patterns

Check it out now on O’Reilly

Dive in for free with a 10-day trial of the O’Reilly learning platform—then explore all the other resources our members count on to build skills and solve problems every day.

how to write task void in c#

DEV Community

DEV Community

Dev Leader

Posted on Jan 28, 2023 • Updated on Jan 29, 2023 • Originally published at devleader.ca

How to Tame “async void” in C#

(This was originally posted on my blog as a full article )

You’re an intermediate dotnet programmer and you mostly know your way around using Tasks. You sprinkle async and await through your code, and everything is working just as expected. You’ve heard time and time again that you always want the return types of your asynchronous methods to be a Task (or Task) and that async void is essentially the root of all evil. No sweat.

One day you go to wire up an event handler using the syntax myObject.SomeEvent += SomeEventHandler, and your event handler needs to await some asynchronous code. You take all of the right steps and change your method signature to get that beautiful async Task added in, replacing void. But suddenly you get a compile error about your event handler not being compatible.

You feel trapped. You’re scared. And then you do the unspeakable…

You change your method signature for your event handler to async void and suddenly all of your compilation problems disappear right before your eyes. You hear the voices of all of the legendary dotnet programmers you look up to echoing in your mind: “What are you doing?! You cannot commit such a heinous coding crime!”. But it’s too late. You’ve succumbed to the powers of async void and all of your problems have appeared to vanish.

That is, until one day it all falls apart. And that’s when you did a search on the Internet and found this article.

Welcome, friend.

What’s Actually Wrong With async void?

Let’s start here with the basics. Here are a few of dangers of using async void in your C# code:

Exceptions thrown in an “async void” method cannot be caught in the same way as they can in an “async Task” method. When an exception is thrown in an “async void” method, it will be raised on the Synchronization Context, which can cause the application to crash.

Because “async void” methods cannot be awaited, they can lead to confusing and hard-to-debug code. For example, if an “async void” method is called multiple times, it can lead to multiple instances of the method running concurrently, which can cause race conditions and other unexpected behavior.

I’d be willing to bet you’re here because of the first point. Your application is experiencing weird crashes, and you’re having a heck of a time diagnosing the issue and getting traces. We are unable to (traditionally) wrap calls to async void methods in try/catch blocks and actually have them work as we’d expect.

I wanted to demonstrate this with a simple bit of code that you can literally try out in your browser . Let’s discuss the code below (which, by the way, is using the top level statements feature of .NET 7.0 so if you’re not used to seeing a C# program without a static void main… don’t be shocked!):

As the code above shows, we have three examples scenarios to look at. And seriously, jump over to the link and try them each out by uncommenting one of those lines at a time.

In scenario 1, we see our old faithful friend async Task. This task is going to throw an exception when we run the program, and since we are awaiting an async Task, the wrapping try/catch block is able to catch the exception just as we’d expect.

In scenario 2, this might seem like some code that brought you here. The dreaded async void. When you run this one, you’ll notice that we print information that we’re about to throw the exception… But then we never see the indication that we’re leaving the async void method! In fact, we just see the line indicating the program has ended. How spooky is that?

In scenario 3, this might look like an attempt you have tried to solve your async void woes. Surely if we wrap the async void in a Task, we can await that, and then we’ll go back to being safe… right? Right?! No. In fact, in .NET Fiddle you’ll actually see that it prints “Unhandled exception”. That’s not something we have in our code, that’s something scarier firing off AFTER our program is complete.

What’s Actually Actually The Problem?

Fundamentally, no matter how you try massage code around, if you have an event handler the return type of it must be void to hook up to a C# event using the + operator.

This means that even if you try to refactor all of your code to avoid this, you’re only “fixing” the issue by running away from it. And yes, while I agree if possible you should try and write code that doesn’t trap you into crappy patterns, sometimes curiosity wins out.

Is there a way that we could still have our event handlers as async void (so that we can await things inside of them)? Yes, of course! And the added bonus of the method that we’re going to dive into is that it’s not restricted to just event handlers. You can leverage this pattern on any old async void method you have laying around.

Do I recommend it? Absolutely not. I often find myself designing objects with events on them and I try to restrict my usage to this exact scenario. You know, the one that all of the C# gurus say “Fine, if you MUST use async void then… Make sure it’s for an event handler on a button or something”.

So let’s look at how we can make that a less painful experience going forward.

Waking Up From The Nightmare

You’ve been patient enough, so let’s dive right into it. If you want to follow along with a working demo right in your browser, check out this link .

Here’s the demo code, which we’ll cover right after:

Understanding The Scenarios

There are two classes of things that we can play with in this code snippet:

  • Toggle between what TaskThatIsReallyImportantAsync does. You can either safely print to the console, or have it throw an exception so you can experiment with the happy vs bad path. This alone isn’t the focus of the article, but it allows you to try different situations.
  • Toggle the behavior of RaiseEventAsync, which will show you the not-so-great behavior of async void compared to our solution! Mix this with the previous option to see how we can improve our ability to catch exceptions.

How It Works

This solution is something I heavily borrowed from Oleg Karasik. In fact, his original article does such a fantastic job explaining how he built out the algorithm feature at a time. So I give full credit to him because without his post, I never would have put together what I am showing here.

The main take aways regarding how this works are that:

  • We can use a custom synchronization context, specifically for handling events, that take a custom completed/failed callback.
  • We can use reflection to check for AsyncStateMachineAttribute to see if our handler is truly marked as async or not.
  • GetInvocationList allows us to get the entire chain of handled registered to an event.
  • DynamicInvoke allows us to invoke the delegate without the compiler screaming about types.

When you combine the above, we can also layer in a couple of other features:

  • forceOrdering: This boolean flag can force each handler to run in the order that they were registered or if it’s disabled, the handlers can run asynchronously with each other.
  • stopOnFirstError: This boolean flag can prevent the code from firing off the subsequent event handlers if one of them raises an exception.

In the end, we are able to set information on a TaskCompletionSource instance that indicates completion or an exception being tracked.

What’s Next?

If you’d like to see how I expanded upon some of this code for my own projects, please continue reading the full original article . I hope this article serves as a reminder to folks that when we hear “It can’t be done” or “Never do X” or “Always do Y”, we shouldn’t always stop in our tracks without trying to understand further. When we have constraints, this is when we come up with the most creative solutions!

Top comments (0)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

nikl profile image

Inapp Messaging Intgr.- Native for react, ngx, flutter, vue, Next,js, iOS

Nik L. - Apr 3

lilxyzz profile image

2024 Cheat Sheet Collection

Travis - Mar 17

aymanepraxe profile image

MVC Sucks, and We Should Learn from It

aymane aallaoui - Apr 2

ssukhpinder profile image

Day 15 of 30-Day .NET Challenge: Lazy Initialization

Sukhpinder Singh - Apr 3

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

how to write task void in c#

C# Asynchronous Programming , C#.Net

Tasks in C#

Tasks in C# is an object representing an operation or work that executes in asynchronous manner. It was introduced in .NET framework 4.0 to support asynchronous programming.

It’s a basic component of the Task Parallel Library (TPL) and is mostly used for asynchronous programming and parallel processing. In this blog, we will explore more details regarding Task and its usage.

What is a Task in C#?

In C#, Task is basically used to implement asynchronous programming model, the .Net runtime executes a Task object asynchronously on a separate thread from the thread pool.

  • Whenever you create a Task , the TPL (Task Parallel Library) instructs the Task Scheduler to execute the operation in a separate thread.
  • The Task Scheduler is responsible to execute the Task,  by default it requests a worker thread from the Thread Pool to execute the Task.
  • Here, the thread pool manager determines whether to create a new thread or reuse an existing thread from the thread pool to execute the operation.

Task_In_C_Sharp

The TPL abstracts the complexity of managing threads and synchronization, it allows you to focus on defining tasks and the high-level structure of their asynchronous code.

Creating Tasks in C#?

To create a Task in C#, first you need to import System.Threading.Tasks namespace into your program, then you can use the Task class to create object and access its properties.

Example – 1: Creating Tasks in C# using Task class and Start method.

In below example,

  • We have created a Task object as Task t , passing the method PrintEvenNumbers in the constructor.
  • Finally, we invoke the Task t by t . Start ( )  method.

When we run above example, it generates below output.

Tasks in C# OutPut 1.0

The output clearly demonstrates that the Main program executes in thread number: 1 and the Task executes in a separate thread having thread number as 3.

Different ways of creating Tasks in C#:

There are various ways available in C#.Net 4.0 to create a Task object. Please find some of the different ways as follows.

1) Task creation using Factory method:   You can use Task . Factory ( ) method to creates a Task instance and invoke it in a single line of code, as follows.

2) Task creation using Action Generic Delegate:  You can use below syntax to create a Task using Action type ( Generic Delegate ).

3) Task creation using a Delegate:  In below code sample, we are using delegate keyword to create a Task instance and then invoking it.

Similarly, we can also use Task . Run ( ) method to create a Task object and invoke it in single line, as follows.

4) Task creation using Lambda and named method:  In below code sample, we are using lambda and named method expression to create a Task instance and then invoking it.

Example – 2: Example of a Task creation and execution flow

Let’s go through an example and see the Task creation and execution in detail.

  • We have created a method as PrintOddEvenNumbers that prints odd and even numbers.
  • In the Main method, we have created a task instance Task t = new Task ( PrintOddEvenNumbers ) ; , assigned it to the method and then invoking it by calling t . start ( )  .
  • If you look at the console output, once the Task executes successfully, it prints odd and even numbers less than 10 on the console window.

Tasks in C# Out Put 1.1

In the above output window, if you look at the messages, then it’s clear that the Task executed on a separated Child thread ( Thread  Number: 3 ), whereas Main method executed on main thread ( Thread ID : 1 ).

Also, if you observe above result,

  • Both threads ( Main and Child ) started its execution simultaneously (asynchronously), however the Main thread didn’t wait for the Child thread to complete.
  • The Child  thread continued its execution until it finishes its task even after completion of Main thread execution.

If you want to make the Main thread execution to wait until the other tasks complete its execution, you can do that by using Task . Wait method. To know more about this, please check my next article Tasks in C#  Extended.

Key Points of Tasks in C#:

Following are some of the key points that you need to remember about Tasks.

  • You can use Task to run multiple operations concurrently, using Task you can continue executing other tasks or operations while the Task runs in the background.
  • If a Task produces a result, you can access it using the Result property, however this can cause blocking if the task isn’t completed.
  • You can chain tasks together using continuations, specifying what should happen next when a Task completes, enhancing workflow control.
  • Exceptions thrown within a Task are captured and stored until the task is awaited or observed. You should handle exceptions explicitly using try and catch blocks.
  • You can gracefully cancel a Task using cancellation tokens, which is useful for managing tasks that may take a longer time.

Conclusion:

In conclusion, a Task in C# helps you manage asynchronous and parallel programming, it makes your program more responsive and efficient when dealing with time-consuming operations. Please check our next article here on below topic.

  • How to wait for Task to complete?
  • Get return value from Tasks?

Share this:

2 thoughts on “ tasks in c# ”.

Add Comment

Very helpful blog 👍

Amazing explanation Task article.

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed .

Discover more from

Subscribe now to keep reading and get access to the full archive.

Type your email…

Continue reading

  • .NET Framework
  • C# Data Types
  • C# Keywords
  • C# Decision Making
  • C# Delegates
  • C# Constructors
  • C# ArrayList
  • C# Indexers
  • C# Interface
  • C# Multithreading
  • C# Exception
  • short keyword in C#
  • char keyword in C#
  • sbyte Keyword in C#
  • Readonly in C#
  • decimal keyword in C#
  • bool Keyword in C#
  • typeof Operator Keyword in C#
  • Static keyword in C#
  • C# | this Keyword
  • Difference between Ref and Out keywords in C#
  • float keyword in C#
  • int Keyword in C#
  • Difference between readonly and const keyword in C#
  • uint keyword in C#
  • double Keyword in C#
  • ulong keyword in C#
  • var keyword in C#
  • Access Modifiers in C#

void Keyword in C#

Keywords are the words in a language that are used for some internal process or represent some predefined actions. void is a keyword, it is a reference type of data type and used to specify the return type of a method in C#. It is an alias of System.Void .

Note: void cannot be used as a parameter if there is no parameter in a C# method.

Please Login to comment...

Similar reads.

  • CSharp-keyword
  • CBSE Exam Format Changed for Class 11-12: Focus On Concept Application Questions
  • 10 Best Waze Alternatives in 2024 (Free)
  • 10 Best Squarespace Alternatives in 2024 (Free)
  • Top 10 Owler Alternatives & Competitors in 2024
  • 30 OOPs Interview Questions and Answers (2024)

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Asynchronous programming scenarios

  • 4 contributors

If you have any I/O-bound needs (such as requesting data from a network, accessing a database, or reading and writing to a file system), you'll want to utilize asynchronous programming. You could also have CPU-bound code, such as performing an expensive calculation, which is also a good scenario for writing async code.

C# has a language-level asynchronous programming model, which allows for easily writing asynchronous code without having to juggle callbacks or conform to a library that supports asynchrony. It follows what is known as the Task-based Asynchronous Pattern (TAP) .

Overview of the asynchronous model

The core of async programming is the Task and Task<T> objects, which model asynchronous operations. They are supported by the async and await keywords. The model is fairly simple in most cases:

  • For I/O-bound code, you await an operation that returns a Task or Task<T> inside of an async method.
  • For CPU-bound code, you await an operation that is started on a background thread with the Task.Run method.

The await keyword is where the magic happens. It yields control to the caller of the method that performed await , and it ultimately allows a UI to be responsive or a service to be elastic. While there are ways to approach async code other than async and await , this article focuses on the language-level constructs.

In some of following examples System.Net.Http.HttpClient class is used to download some data from a web service. The s_httpClient object used in these examples is a static field of Program class (please check the complete example):

private static readonly HttpClient s_httpClient = new();

I/O-bound example: Download data from a web service

You may need to download some data from a web service when a button is pressed but don't want to block the UI thread. It can be accomplished like this:

The code expresses the intent (downloading data asynchronously) without getting bogged down in interacting with Task objects.

CPU-bound example: Perform a calculation for a game

Say you're writing a mobile game where pressing a button can inflict damage on many enemies on the screen. Performing the damage calculation can be expensive, and doing it on the UI thread would make the game appear to pause as the calculation is performed!

The best way to handle this is to start a background thread, which does the work using Task.Run , and await its result using await . This allows the UI to feel smooth as the work is being done.

This code clearly expresses the intent of the button's click event, it doesn't require managing a background thread manually, and it does so in a non-blocking way.

What happens under the covers

On the C# side of things, the compiler transforms your code into a state machine that keeps track of things like yielding execution when an await is reached and resuming execution when a background job has finished.

For the theoretically inclined, this is an implementation of the Promise Model of asynchrony .

Key pieces to understand

  • Async code can be used for both I/O-bound and CPU-bound code, but differently for each scenario.
  • Async code uses Task<T> and Task , which are constructs used to model work being done in the background.
  • The async keyword turns a method into an async method, which allows you to use the await keyword in its body.
  • When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete.
  • await can only be used inside an async method.

Recognize CPU-bound and I/O-bound work

The first two examples of this guide showed how you could use async and await for I/O-bound and CPU-bound work. It's key that you can identify when a job you need to do is I/O-bound or CPU-bound because it can greatly affect the performance of your code and could potentially lead to misusing certain constructs.

Here are two questions you should ask before you write any code:

Will your code be "waiting" for something, such as data from a database?

If your answer is "yes", then your work is I/O-bound .

Will your code be performing an expensive computation?

If you answered "yes", then your work is CPU-bound .

If the work you have is I/O-bound , use async and await without Task.Run . You should not use the Task Parallel Library.

If the work you have is CPU-bound and you care about responsiveness, use async and await , but spawn off the work on another thread with Task.Run . If the work is appropriate for concurrency and parallelism, also consider using the Task Parallel Library .

Additionally, you should always measure the execution of your code. For example, you may find yourself in a situation where your CPU-bound work is not costly enough compared with the overhead of context switches when multithreading. Every choice has its tradeoff, and you should pick the correct tradeoff for your situation.

More examples

The following examples demonstrate various ways you can write async code in C#. They cover a few different scenarios you may come across.

Extract data from a network

This snippet downloads the HTML from the given URL and counts the number of times the string ".NET" occurs in the HTML. It uses ASP.NET to define a Web API controller method, which performs this task and returns the number.

If you plan on doing HTML parsing in production code, don't use regular expressions. Use a parsing library instead.

Here's the same scenario written for a Universal Windows App, which performs the same task when a Button is pressed:

Wait for multiple tasks to complete

You may find yourself in a situation where you need to retrieve multiple pieces of data concurrently. The Task API contains two methods, Task.WhenAll and Task.WhenAny , that allow you to write asynchronous code that performs a non-blocking wait on multiple background jobs.

This example shows how you might grab User data for a set of userId s.

Here's another way to write this more succinctly, using LINQ:

Although it's less code, use caution when mixing LINQ with asynchronous code. Because LINQ uses deferred (lazy) execution, async calls won't happen immediately as they do in a foreach loop unless you force the generated sequence to iterate with a call to .ToList() or .ToArray() . The above example uses Enumerable.ToArray to perform the query eagerly and store the results in an array. That forces the code id => GetUserAsync(id) to run and start the task.

Important info and advice

With async programming, there are some details to keep in mind that can prevent unexpected behavior.

async methods need to have an await keyword in their body or they will never yield!

This is important to keep in mind. If await is not used in the body of an async method, the C# compiler generates a warning, but the code compiles and runs as if it were a normal method. This is incredibly inefficient, as the state machine generated by the C# compiler for the async method is not accomplishing anything.

Add "Async" as the suffix of every async method name you write.

This is the convention used in .NET to more easily differentiate synchronous and asynchronous methods. Certain methods that aren't explicitly called by your code (such as event handlers or web controller methods) don't necessarily apply. Because they are not explicitly called by your code, being explicit about their naming isn't as important.

async void should only be used for event handlers.

async void is the only way to allow asynchronous event handlers to work because events do not have return types (thus cannot make use of Task and Task<T> ). Any other use of async void does not follow the TAP model and can be challenging to use, such as:

  • Exceptions thrown in an async void method can't be caught outside of that method.
  • async void methods are difficult to test.
  • async void methods can cause bad side effects if the caller isn't expecting them to be async.

Tread carefully when using async lambdas in LINQ expressions

Lambda expressions in LINQ use deferred execution, meaning code could end up executing at a time when you're not expecting it to. The introduction of blocking tasks into this can easily result in a deadlock if not written correctly. Additionally, the nesting of asynchronous code like this can also make it more difficult to reason about the execution of the code. Async and LINQ are powerful but should be used together as carefully and clearly as possible.

Write code that awaits Tasks in a non-blocking manner

Blocking the current thread as a means to wait for a Task to complete can result in deadlocks and blocked context threads and can require more complex error-handling. The following table provides guidance on how to deal with waiting for tasks in a non-blocking way:

Consider using ValueTask where possible

Returning a Task object from async methods can introduce performance bottlenecks in certain paths. Task is a reference type, so using it means allocating an object. In cases where a method declared with the async modifier returns a cached result or completes synchronously, the extra allocations can become a significant time cost in performance critical sections of code. It can become costly if those allocations occur in tight loops. For more information, see generalized async return types .

Consider using ConfigureAwait(false)

A common question is, "when should I use the Task.ConfigureAwait(Boolean) method?". The method allows for a Task instance to configure its awaiter. This is an important consideration and setting it incorrectly could potentially have performance implications and even deadlocks. For more information on ConfigureAwait , see the ConfigureAwait FAQ .

Write less stateful code

Don't depend on the state of global objects or the execution of certain methods. Instead, depend only on the return values of methods. Why?

  • Code will be easier to reason about.
  • Code will be easier to test.
  • Mixing async and synchronous code is far simpler.
  • Race conditions can typically be avoided altogether.
  • Depending on return values makes coordinating async code simple.
  • (Bonus) it works really well with dependency injection.

A recommended goal is to achieve complete or near-complete Referential Transparency in your code. Doing so will result in a predictable, testable, and maintainable codebase.

Complete example

The following code is the complete text of the Program.cs file for the example.

Other resources

  • The Task asynchronous programming model (C#) .

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

IMAGES

  1. Easy Programming

    how to write task void in c#

  2. C# static void methods

    how to write task void in c#

  3. Void function example (C++ programming tutorial)

    how to write task void in c#

  4. How to Control the Result of a Task in C#

    how to write task void in c#

  5. C# Programming

    how to write task void in c#

  6. C++ Tutorial- Void Functions

    how to write task void in c#

VIDEO

  1. return keyword inside a method whose return type is void (Core Java Interview Question #175)

  2. What is the difference between static,public & void C# #shorts

  3. Converting an Image to Byte Array in C#

  4. how to write task 2 full structure

  5. C# Asynchronous Programming : 22 How to Cancel a Task in C# using Cancellation Token in Telugu

  6. C# Multithreading Task/Async/Await Part 2: C# Code

COMMENTS

  1. c#

    async Task<T> method() await can be used to wait till the execution is completed and it will return value of type T. async Task method() await can be used to wait till the execution is completed but no data is returned. async void method() can't be awaited and no data is returned [Example: async event execution]

  2. c#

    6. Just mark doSequence as async (assuming it uses await ): private async Task doSequence() Also, it's a good idea to return this Task in the delegate you pass to Task.Run: SequenceTask = await Task.Run(() => doSequence()); I would like to create a task to run serial commands on. This leads me to believe that using async and Task may not be the ...

  3. Async return types

    In this article. Async methods can have the following return types: Task, for an async method that performs an operation but returns no value.; Task<TResult>, for an async method that returns a value. void, for an event handler.; Any type that has an accessible GetAwaiter method. The object returned by the GetAwaiter method must implement the System.Runtime.CompilerServices ...

  4. Asynchronous programming with async, await, Task in C#

    In the above example, in the static async Task<int> LongProcess() method, Task<int> is used to indicate the return value type int. int val = await result; will stop the main thread there until it gets the return value populated in the result. Once get the value in the result variable, it then automatically assigns an integer to val.. An async method should return void, Task, or Task<TResult ...

  5. The Task Asynchronous Programming (TAP) model with async and await'

    The return type is Task<int> (See "Return Types" section for more options). The method name ends in Async. In the body of the method, GetStringAsync returns a Task<string>. That means that when you await the task you'll get a string (contents). Before awaiting the task, you can do work that doesn't rely on the string from GetStringAsync.

  6. Understanding C# Methods: Async, Void, and Task

    Task represents an asynchronous operation; Task provides a way to manage and control asynchronous operations; Async is used to mark a method as asynchronous; Async indicates that a method can be awaited and executed asynchronously. Conclusion: In this article, we explored the concepts of async methods, void methods, and Task in C#.

  7. Async/Await

    Async void methods have different composing semantics. Async methods returning Task or Task<T> can be easily composed using await, Task.WhenAny, Task.WhenAll and so on. Async methods returning void don't provide an easy way to notify the calling code that they've completed.

  8. Task in C# with Examples

    Task in C#. In C#, when we have an asynchronous method, in general, we want to return one of the following data types. Task and Task<T>. ValueTask and ValueTask<T>. We will talk about ValueTask later, Now let us keep the focus on Task. The Task data type represents an asynchronous operation. A task is basically a "promise" that the ...

  9. Awaiting an async void method in .NET

    async void methods are not a good way to define async methods. You should return a Task or ValueTask instead. The main point is to be able to await the method. But, is it possible to await an async void method? I don't say you should use async void in your code, I'm just questioning the point of not being able to await them…. When you create an async void method, the compiler generates code ...

  10. How Do Tasks Work In C#? Async/Background Threads

    You can use await inside this task to wait for async operations, which in turn return a task themselves. You can start running a Task using Task.Run(Action action). This will queue up the Task on the thread pool, which will run in the background on a different thread. The thread pool takes a queue of tasks, and assigns them to CPU threads for ...

  11. Asynchronous programming in C#

    The Task asynchronous programming model (TAP) provides an abstraction over asynchronous code. You write code as a sequence of statements, just like always. You can read that code as though each statement completes before the next begins. The compiler performs many transformations because some of those statements may start work and return a Task ...

  12. 4. Writing Async Methods

    The first step is to add the async keyword to the method. It appears in the method signature in the same way that the static keyword does. Then, we need to wait for the download using the await keyword. In terms of C# syntax, await acts as a unary operator, like the ! not operator, or the (type) cast operator.

  13. How to Tame "async void" in C#

    using System.Threading.Tasks; Console.WriteLine("Start"); try. {. // NOTE: uncomment the single line for each one of the scenarios below one at a time to try it out! // Scenario 1: we can await an async Task which allows us to catch exceptions. //await AsyncTask(); // Scenario 2: we cannot await an async void and as a result we cannot catch the ...

  14. Tasks in C#

    Different ways of creating Tasks in C#: There are various ways available in C#.Net 4.0 to create a Task object. Please find some of the different ways as follows. 1) Task creation using Factory method: You can use Task. Factory method to creates a Task instance and invoke it in a single line of code, as follows.

  15. Task-based asynchronous programming

    Creating child tasks. When user code that's running in a task creates a task with the AttachedToParent option, the new task is known as an attached child task of the parent task. You can use the AttachedToParent option to express structured task parallelism because the parent task implicitly waits for all attached child tasks to finish. The following example shows a parent task that creates 10 ...

  16. void Keyword in C#

    Keywords are the words in a language that are used for some internal process or represent some predefined actions. void is a keyword, it is a reference type of data type and used to specify the return type of a method in C#. It is an alias of System.Void. Syntax: public void function_name([parameters]) {. //body of the function.

  17. async Task vs async void in C#

    The Task return type is used when an async method does not return a value. The compiler splits an async method into two parts; a caller and a listener. The Task type allows the listener to await a response. Await is like a marker that tells the code were to resume when the async task completes. An async void return type loses the ability to ...

  18. c#

    350. Best practice is to mark function async void only if it is fire and forget method, if you want to await on, you should mark it as async Task. In case if you still want to await, then wrap it like so await Task.Run(() => blah()) await Task.Run(() => blah()) is misleading.

  19. Asynchronous programming scenarios

    The core of async programming is the Task and Task<T> objects, which model asynchronous operations. They are supported by the async and await keywords. The model is fairly simple in most cases: For I/O-bound code, you await an operation that returns a Task or Task<T> inside of an async method. For CPU-bound code, you await an operation that is ...

  20. c#

    You should be using. static async Task Main() {. await example1(); } In your first example your process will exit directly after reaching the first await. And this will prevent anything after any await to run. Making the main method async Task Main() will ensure your process stays alive until the returned task completes.