How to call multiple methods parallelly by using async programming in C# - c#

public class Program
{
public static void Main(string[] args)
{
Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = method1();
var m2 = method2();
await Task.WhenAll(m1, m2);
}
private static async Task method1()
{
Console.WriteLine("Method1 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method1 - End");
}
private static async Task method2()
{
Console.WriteLine("Method2 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method2 - End");
}
}
The above code returning below out
Method1 - Start
Method1 - End
Method2 - Start
Method2 - End
I want an output like
Method1 - Start
Method2 - Start
Method1 - End
Method2 - End
how to achieve that basically how to run async methods in parallel

Option A - with Task.Delay
public class Program
{
public static async Task Main()
{
await Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = method1();
var m2 = method2();
await Task.WhenAll(m1, m2);
}
private static async Task method1()
{
Console.WriteLine("Method1 - Start");
await Task.Delay(1000);
Console.WriteLine("Method1 - End");
}
private static async Task method2()
{
Console.WriteLine("Method2 - Start");
await Task.Delay(1000);
Console.WriteLine("Method2 - End");
}
}
Option B - with Task.Run
public class Program
{
public static async Task Main()
{
await Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = Task.Run(() => method1());
var m2 = Task.Run(() => method2());
await Task.WhenAll(m1, m2);
}
private static void method1()
{
Console.WriteLine("Method1 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method1 - End");
}
private static void method2()
{
Console.WriteLine("Method2 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method2 - End");
}
}

Or you can use Task.Yield().
public class Program
{
public static void Main(string[] args)
{
Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = method1();
var m2 = method2();
await Task.WhenAll(m1, m2);
}
private static async Task method1()
{
await Task.Yield();
Console.WriteLine("Method1 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method1 - End");
}
private static async Task method2()
{
await Task.Yield();
Console.WriteLine("Method2 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method2 - End");
}
}
This one is a bit "more parallel" than using Task.Delay() because it immediately yields back an uncomplete task, but with delay the "asynchronicity" only happens when you reach that line of code. If you have long running sync code before the delay, that will delay the execution of subsequent methods (in this case method2).
Edit
a more detailed explanation on When would I use Task.Yield()?

Related

Async Functions of Entity Framework not running properly

As I know, asynchronous functions return immediately. The sample code below confirms me.
static void Main(string[] args)
{
StartTasks2();
Console.ReadKey();
}
private static void StartTasks2()
{
Console.WriteLine($"Task2 Started: {DateTime.Now:s.ffff}");
AddPersonFake();
Console.WriteLine($"Task2 Finished: {DateTime.Now:s.ffff}");
}
private static async void AddPersonFake()
{
Console.WriteLine($"AddPersonFake Started: {DateTime.Now:s.ffff}");
await Task.Delay(2000);
Console.WriteLine($"AddPersonFake Finished: {DateTime.Now:s.ffff}");
}
But this code is not working (I'm waiting for the result as above):
static void Main(string[] args)
{
StartTasks1();
Console.ReadKey();
}
private static void StartTasks1()
{
Console.WriteLine($"Task1 Started: {DateTime.Now:s.ffff}");
AddPerson();
Console.WriteLine($"Task1 Finished: {DateTime.Now:s.ffff}");
}
private static async void AddPerson()
{
Console.WriteLine($"AddPerson Started: {DateTime.Now:s.ffff}");
using ( TempDbContext context = new TempDbContext() )
{
context.Persons.Add(new Person());
await context.SaveChangesAsync();
}
Console.WriteLine($"AddPerson Finished: {DateTime.Now:s.ffff}");
}
How can I return immediately from AddPerson()?
From what I learned here on StackOverflow yestarday, you can do it using:
private static async void AddPerson() {
await Task.Yield();
Console.WriteLine($"AddPerson Started: {DateTime.Now:s.ffff}");
using ( TempDbContext context = new TempDbContext() ) {
context.Persons.Add(new Person());
await context.SaveChangesAsync();
}
Console.WriteLine($"AddPerson Finished: {DateTime.Now:s.ffff}");
}
Task.Yield() will start incompeleted Task and when awaiting it, that is the place where your asynchronous code will start.
In your original code, method AddPerson is running synchronously until it reaches the first await

How make method start new execution only when finished previous execution

Hello How make method MethodA start new execution only when finished previous execution?
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
MethodB();
MethodC();
}
public static void MethodA ()
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
public static void MethodB()
{
Task.Run(() => MethodA());
}
public static void MethodC()
{
Task.Run(() => MethodA());
}
}
In this case I have this result
Hello World
Start
Start
Stop
Stop
But I need something like this
Hello World
Start
Stop
Start
Stop
The simplest way is to create a static locking object and reference that in MethodA:
private static readonly object _methodALockObject = new object();
public static void MethodA()
{
lock(_methodALockObject)
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
}
Try to use async and await:
public static void Main()
{
Task.Run(async () =>
{
await MethodB();
await MethodC();
}).GetAwaiter().GetResult();
}
public static void MethodA()
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
public async static Task MethodB()
{
await Task.Run(() => MethodA());
}
public async static Task MethodC()
{
await Task.Run(() => MethodA());
}
async and await keywords help to make your asynchronous code to be executed in syncronous order.

Not seeing output after using Task delay

I am using an online editor for testing some C# code : https://repl.it/
I am not able to get the task after Task.Delay.
Why is this C# code not working as intended?
using System.IO;
using System;
using System.Reflection;
using System.Threading.Tasks;
class Input {
public Input() {
}
public async void hello()
{
Console.WriteLine("some task");
await Task.Delay(1000);
Console.WriteLine("after some time");
}
}
class SomeExample {
public static void Main(string[] args) {
Input std1 = new Input( );
std1.hello();
}
}
Method hello should return Task, not void. Method Main should be async Task to be able to await hello. Also you need to await std1.hello() call:
public async Task hello()
{
Console.WriteLine("some task");
await Task.Delay(1000);
Console.WriteLine("after some time");
}
public static async Task Main(string[] args)
{
Input std1 = new Input( );
await std1.hello();
}
What you have now is situation when Main method finishes its execution before hello method (because it not awaited).
Fixes: Change your method return type from void to Task. Make the console wait by adding Console.ReadLine() so that you can see the output ("after some time") and lastly, tell the method to wait and don't finish execution by adding Wait().
Hope this works.
class Input
{
public Input()
{
}
public async Task hello()
{
Console.WriteLine("some task");
await Task.Delay(1000);
Console.WriteLine("after some time");
Console.ReadLine();
}
}
class SomeExample
{
public static void Main(string[] args)
{
Input std1 = new Input();
std1.hello().Wait();
}
}
For now it seems this code is doing my work. I don't need to use async or Task keywords.
using System.IO;
using System;
using System.Threading.Tasks;
class Input
{
public Input()
{
}
public void hello()
{
Console.WriteLine("some task");
Task.Delay(1000).Wait();
Console.WriteLine("after some time");
}
}
class SomeExample
{
public static void Main(string[] args)
{
Input std1 = new Input();
std1.hello() ;
}
}

How to use async to execute callback delegate

I have a callback function which needs to takes several seconds to process and should be a async method, but I can't find a way to execute this async callback by await because it must be a Delegate param in the calling method.
Here is some piece of code:
async Task Callback(){//do some callback..}
async Task DoSomething(Func<Task> callback){//I want to execute the callback like: await callback();}
async void Main(){ DoSomething(Callback);}
Sorry for my poor english, any idea to do that? Thanks!
You will have to await first call itself.
change
async void Main(){ DoSomething(Callback);}
to
async void Main(){ await DoSomething(Callback);}
After that It should work, I tested with your sample code. Please verify at your end.
class Program
{
static void Main(string[] args)
{
(new Test()).Main();
Console.ReadKey();
}
}
public class Test
{
async Task Callback()
{
Console.WriteLine("I'm in callback");
}
async Task DoSomething(Func<Task> callback)
{
Console.WriteLine("I'm in DoSomething");
await callback();
}
public async void Main()
{
Console.WriteLine("I'm in Main");
await DoSomething(Callback);
Console.WriteLine("Execution completed");
}
}
Here is output

Why my task work only once?

I want to print every 2 sec number but and in the end i get only 0 what i need to do to get this every 2 sec?
result:
0
1
.
.
49
private static void Main(string[] args) {
Send();
}
public static async Task Send() {
for (int i = 0; i < 50; i++) {
Console.WriteLine(i);
await Task.Delay(2000);
}
}
well, simply because your Main method won't wait for the send method to finish and you can't use the await keyword in order for that to happened since the compiler won't allow an async Main, in that case you could simple use a Task.Run
private static void Main(string[] args)
{
Task.Run(async () =>
{
await Send();
}).Wait();
}
public static async Task Send()
{
for (int i = 0; i < 50; i++)
{
Console.WriteLine(i);
await Task.Delay(2000);
}
}
What you are missing is a Console.ReadLine() call, to halt the console from exiting the program before your task gets executed. Tested the code below and it works.
private static void Main(string[] args)
{
Send();
Console.ReadLine();
}
public static async Task Send()
{
for (int i = 0; i < 50; i++)
{
Console.WriteLine(i);
await Task.Delay(2000);
}
}
Building on Josephs answer, but in a more general "How to do asynchronous console apps"-way
Using asynchronous code in console apps can be a bit tricky. I generally use a substitute MainAsync method that the original Main() calls and makes a blocking wait on.
Here comes an example of how it could be done:
class Program
{
static void Main(string[] args)
{
Task mainTask = MainAsync(args);
mainTask.Wait();
// Instead of writing more code here, use the MainAsync-method as your new Main()
}
static async Task MainAsync(string[] args)
{
await Send();
Console.ReadLine();
}
public static async Task Send()
{
for (int i = 0; i < 50; i++)
{
Console.WriteLine(i);
await Task.Delay(2000);
}
}
}

Categories