Async all the way vs. Task.Run on a simple calculation method - c#

I've started to dive into aync programming and I want to execute a very simple add method as an async operation.
One of the things i've read is that truly async program does not require thread switching => that means Task.Run(..) can be avoided.
This is how I've implemented an add method:
public class TaskSimpleExample
{
public static void SimpleCalcExample()
{
// Will perform in background
Task<int> resultTask = Task.Run(() => BeginCalcNumbers(6, 6));
Console.WriteLine("Doing Work");
Console.WriteLine("Doing More Work");
Console.WriteLine("Doing Extra Work");
resultTask.Wait();
Console.WriteLine("Work is done!");
}
static int BeginCalcNumbers(int number1, int number2)
{
int result = Add(number1, number2);
Console.WriteLine(result);
return result;
}
static int Add(int number1, int number2)
{
int result = number1 + number2;
return result;
}
}
Unfortunately, I understand that it has nothing to do with async. It just opens another thread and runs in the background.
I've failed to convert this code to use async & await (and eliminate Task.Run). Is it possible ? (Please notice I need to continue after the callback in other place in the method using resultTask.Wait()).

What you know about Task.Run is absolutely correct and that's pretty much the point of using Task.Run
Using Task.Run will execute a method on a thread pool thread and return a task that represents the completion of the method.
As Stepthen Cleary suggest, you should use Task.Run only to call CPU-bound methods.
Another important thing to mention is that you should use Task.Run to actually call the method that does heavy CPU-bound work and not use Task.Run in the implementation of the method.
Here's a good example on how to use Task.Run properly:
class MyService
{
public int CalculateMandelbrot()
{
// Tons of work to do in here!
for (int i = 0; i != 10000000; ++i)
;
return 42;
}
}
...
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(() => myService.CalculateMandelbrot());
}
Also you should read Task.Run Etiquette and Proper Usage and Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation if you are interested in learning more about Task.Run

Related

C# - async/await print order

I am trying to understand how async and await works so i wrote this little program to try and print "b" before "a" but it's not working and i can't figure it out.. any help? :)
public class program
{
static async Task Main()
{
await a();
b();
}
async static Task a()
{
Console.WriteLine("Waiting for a");
for (int i = 0; i < 100000000; i++)
if (i % 1000000 == 0)
Console.Write(".");
Console.WriteLine("\na");
}
static void b()
{
Console.WriteLine("b");
}
}
Lets refine your code. First it doesn't work, because you told the code to await a(), and so nothing after that line can run before (or during) it. Lets fix it:
static async Task Main()
{
var task = a();
b();
await task;
}
However that is not enough, it still doesn't work. It still runs a() before b() because your a method is not asynchronous. In fact it is synchronous. Just because you use async/await it doesn't make the code automatically asynchronous. You'll need more than that. One way is to add await Task.Yield() which is truely asynchronous call, even though it does nothing (except for allowing the switch to happen). Like this:
async static Task a()
{
Console.WriteLine("Waiting for a");
for (int i = 0; i < 100000000; i++)
if (i % 1000000 == 0)
{
Console.Write(".");
await Task.Yield();
}
Console.WriteLine("\na");
}
Now you will see b() running in the middle of a(). You can play around with the await Task.Yield(); call, and put it in different places to see different result.
This is still a bit primitive example. It would be better to make b() asynchronous as well. And use delays. Like this:
public class program
{
static async Task Main()
{
var task1 = a();
var task2 = b();
await task1;
await task2;
}
async static Task a()
{
Console.WriteLine("Waiting for a");
for (var i = 0; i < 100; i++)
{
Console.Write(".");
await Task.Delay(20);
}
Console.WriteLine("\na");
}
static async Task b()
{
await Task.Delay(200);
Console.WriteLine("b");
}
}
Note that I've slightly modified your a() so that it is more time dependent, less cpu-speed dependent.
Of course you have a thread-safety issue now, which in this case is ok since Console and Task methods are thread-safe. But generally you have to be aware that when two or more Tasks run concurrently then they may run on different threads, and thus you have to make the code thread-safe.
There are 2 problems.
Await is being used incorrectly
You use await to ensure whichever async method is called is completed before any subsequent code is executed.
As freakish said in his answer, you can assign the task from method a to a variable and await it after method b.
Method a isn't actually asynchronous
There isn't any thing that can actually be awaited in the method so it would just run synchronously and complete before method b. Adding something that can be awaited like Task.Yeild (as freakish has stated) would resolve the issue.
I would recommend reading more about asynchronous programming, here is a good place to start: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

Is there any difference between normal lambda and async lambda below?

Assume I have a library as follows for both non-UI based apps (ASP.NET) and UI based apps (WinForm and WPF). Unfortunately I cannot avoid mixing IO-bound work and CPU-bound work but I let the consumers invoke DummyWorkAsync via Task.Run or not based on their application types (non-UI or UI based apps).
class DummyService
{
public static async Task<int> DummyWorkAsync()
{
// Do some I/O first.
await Task.Delay(1000);
// Tons of work to do in here!
for (int i = 0; i != 10000000; ++i)
;
// Possibly some more I/O here.
await Task.Delay(1000);
// More work.
for (int i = 0; i != 10000000; ++i)
;
return 0;
}
}
This allows UI-based consumer to properly use Task.Run to call the service, while ASP.NET clients would just call the method directly as follows.
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(() => DummyService.DummyWorkAsync());
}
public class Home: Controller
{
public async Task<ActionResult> IndexAsync()
{
var result = await DummyService.DummyWorkAsync();
return View(result);
}
}
Question
I am interested in the UI-based apps. Is there any difference if I use
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(async () => await DummyService.DummyWorkAsync());
}
rather than
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(() => DummyService.DummyWorkAsync());
}
?
No, there is no (significant) difference. You are basically asking what's the difference between
static Task<int> Something() {
return SomethingAsync();
}
and
static async Task<int> Something() {
return await SomethingAsync();
}
Except in your case there is one more wrapping task (Task.Run), so differences in exceptions propagation for example which you may find in another questions on the same issue are not relevant in this case.
Because of that - just use
await Task.Run(() => DummyService.DummyWorkAsync());
That said, reasons for doing that are not that clear. Since your IO goes first - you can use ConfigureAwait(false) to prevent returning control to current synchronization context (which is good practice for libraries anyway). In that case, after your first await the rest (heavy CPU work) will be executed on thread pool thread (with default scheduler at least), so you won't need to use Task.Run in the first place:
public static async Task<int> DummyWorkAsync()
{
// Do some I/O first.
await Task.Delay(1000).ConfigureAwait(false);
// Tons of work to do in here!
// no problem, we are not on UI thread anyway
for (int i = 0; i != 10000000; ++i)
;
// Possibly some more I/O here.
await Task.Delay(1000).ConfigureAwait(false);
// More work.
for (int i = 0; i != 10000000; ++i)
;
return 0;
}

Confusion on async and await logic in c#?

i have a great confusion while working with the async and await.
My logic is simple, i have a method which will cause a delay of 15 seconds, like this
public static Task<int> delay(int num)
{
Task.Delay(15000);
return Task.FromResult(num);
}
now i am calling this method like this
public static async void delayAsync(int num)
{
Console.WriteLine(await delay(num)+"time :"+DateTime.Now);
}
static void Main(string[] args)
{
var details = new details();
Console.WriteLine("## start ##");
for (var i = 0; i < 5; i++)
{
Console.WriteLine("counter: "+i);
delayAsync(i);
}
Console.WriteLine("## finished ##");
Console.Read();
}
my desired output is to get the number one by one after the delay of 15 seconds, but i am getting the results all at once without any pause. am i missing something.
I have gone through this blog and couldnt understand a thing
Here are the steps that you need to achieve this:
Await Task.Delay and return num instead of Task.
public static async Task<int> delay(int num)
{
await Task.Delay(15000);
return num;
}
Make your delayAsync method return Task.
public static async Task delayAsync(int num)
{
Console.WriteLine(await delay(num) + "time :" + DateTime.Now);
}
Wait for the result of the delayAsync in you Main method.
public static void Main(string[] args)
{
Console.WriteLine("## start ##");
for (var i = 0; i < 5; i++)
{
Console.WriteLine("counter: " + i);
delayAsync(i).Wait();
}
Console.WriteLine("## finished ##");
Console.Read();
}
You are not awaiting the Task.Delay
public static async Task<int> delay(int num){
await Task.Delay(15000);
return num;
}
Note that the signature of the method needs to include async. Additionally since you are now using await inside the method, you don't need to explicitly create a Task for the return statement.
Additionally you have to await the delayAsync call in your Main method (note that you cannot make Main async so you have to use a workaround like this: https://stackoverflow.com/a/9212343/868361
my desired output is to get the number one by one after the delay of 15 seconds
When you call an async method that you don't await then the compiler will start it and continue with the rest of the procedures. In your case with the rest of the loop. So the simple solution to get your desired output would be here:
Don't use async methods! Simply make it a serial processing.
To achieve that what you want using async you would have to wait in the loop for the delayAsync method. But this would make the asynchronous processing synchronous and you would end up again in the normal 1 thread serial processing, only having invested a lot of effort to end up from where you started.

Understanding Task based asynchronous pattern C#

I am starting to study C# TAP coding. I don't understand why the code is running synchronously
async private void timer1_Tick(object sender, EventArgs e)
{
SyncCount++;
result1.Text = SyncCount.ToString();
AsyncCount = await CountForALongTimeAsync(AsyncCount);
result2.Text = AsyncCount.ToString();
}
async Task<int> CountForALongTimeAsync(int counter)
{
Thread.Sleep(3000);
counter++;
return counter;
}
async Task<int> CountForALongTimeAsync(int counter)
{
What comes next will be executed until the first awaited async call that actually does some waiting (it's possible that a given call could have all it needs to return immediately, e.g. a service that might hit the internet or might return data from a cache, in which case it won't wait).
There are no awaited calls at all, so the Task returned is returned already completed.
Since the calling await CountForALongTimeAsync is awaiting a task that is returned already completed, it runs synchronously.
The method would be better as:
async Task<int> CountForALongTimeAsync(int counter)
{
await Task.Delay(3000);
counter++;
return counter;
}
Incidentally, the pre await way of doing something very (but not entirely) similar would have been:
Task<int> CountForALongTimeAsync(int counter)
{
return Task.Delay(3000).ContinueWith(t =>
{
++counter;
return counter;
});
}
Considering that these are different ideas of "continuing" after a task might or might not give some insight.
In contrast the closest pre-await way of doing what the code in your question does was:
Task<int> CountForALongTimeAsync(int counter)
{
Thread.Sleep(3000);
counter++;
return Task.FromResult(counter); //FromResult returns an already completed task.
}

does the last call in 'async' call graph need to be synchronous?

For example, in the code below, the last method M2Async is synchronous and does not have async/await as otherwise there would need to be a call to M3Async after await and the call graph would continue?
For clarity (from C# in a Nutshell):
A synchronous operation does its work before returning to the caller.
An asynchronous operation does (most or all of) its work after returning to the caller.
public void Main()
{
Task task = M1Async();
// some work
int i = task.result;
// use i etc
}
private async Task M1Async()
{
int i = await M2Async();
// some work
return i;
}
private Task M2Async()
{
return Task.FromResult(2);
}
That depends a bit on what you mean by "synchronous". In some ways, all methods are synchronous (even async ones) - they just synchronously return something that can be awaited and which might have more things to do once awaited.
No, it doesn't have to be synchronous; your code could just as well be:
private async Task<int> M2Async()
{
return await Task.FromResult(2);
}
or even just (although the compiler will detect that this is a smell, and is secretly synchronous):
private async Task<int> M2Async()
{
return 2;
}
Neither of which would be particularly useful, but; they would work. In reality, most async methods will bottom out at something that is doing async IO - file-system, network, etc. In your example, there is nothing that will actually truly be async anyway - it will all be completed when the await is reached.

Categories

Resources