In a console application I've created a List of Task in which im adding three async tasks:
static void Main(string[] args)
{
List<Task> task_list= new List<Task>();
Task task_1=new Task(async () => await Task_method1());
Task task_2=new Task(async () => await Task_method2());
Task task_3=new Task(async () => await Task_method3());
task_list.Add(task_1);
task_list.Add(task_2);
task_list.Add(task_3);
Task.WaitAll(task_list.ToArray());
foreach (Task t in task_list)
{
Console.WriteLine("Task {0} Status: {1}", t.Id, t.Status);
}
Console.ReadKey();
}
And here's the method definition of 3 Task:
public async Task<HttpResponseMessage> Task_Method1()
{
//Code for Response
return Response;
}
public async Task<HttpResponseMessage> Task_Method2()
{
//Code for Response
return Response;
}
public async Task<HttpResponseMessage> Task_Method3()
{
//Code for Response
return Response;
}
Problem is that they are running parallely, and there's no serialized order of tasks. I searched a lot but get didn't get an appropriate solution for running them in series.
For reference see the image below:
RUN1:
RUN2:
RUN3:
You must have omitted some code, as even if the tasks complete in arbitrary order, your List's order should remain unchanged, yet you show your output with the List's order changing.
Then re actually doing it, perhaps I'm missing something, but if you want them to run in order why not just do:
static void Main(string[] args)
{
MainAsync().Wait();
}
private async Task MainAsync()
{
var response1 = await Task_method1();
var response2 = await Task_method2();
var response3 = await Task_method3();
// Write results, etc.
Console.ReadKey();
}
Related
I simple do not know how to make the following code work, it is suppose to keep running forever inside an infinite loop, and in fact it will work when I remove await Task.Delay from the method Method_FOO, but I need Method_FOO to be async.
I think to make this work the Thread.Start() method needs to be "waitable" (not just the code it runs), but Thread.Start is void. I notice that if I block the execution with eg.: Console.ReadLine it will print the Worked string, but this is not a solution, and is terrible in real life.
This code is just an example, but the threads need to run inside an infinite loop (it is not something I can change), and I need async methods because I need to consume some websockets, and looks like there is no sync client websocket class in C#.
But still, there must be a simple/decent solution for this problem.
public static class Program
{
public static async Task Main(string[] args)
{
var cancellationTokenSource = new CancellationTokenSource();
var thread1 = new Thread(async () => await Run(cancellationTokenSource.Token, "threadName1", Method_FOO));
var thread2 = new Thread(async () => await Run(cancellationTokenSource.Token, "threadName2", Method_FOO));
thread1.Start();
thread2.Start();
}
private static async Task Method_FOO(CancellationToken cancellationToken)
{
Console.WriteLine("It is called...");
await Task.Delay(300, cancellationToken);
//never reach this part
Console.WriteLine("Worked ...");
}
// workd but it is not async
//private static Task Method_FOO(CancellationToken cancellationToken)
//{
// Console.WriteLine("It is called...");
// Console.WriteLine("Worked ...");
// return Task.CompletedTask;
//}
private static async Task Run(CancellationToken cancellationToken, string threadName, Func<CancellationToken, Task> function)
{
try
{
while (true)
{
await function(cancellationToken);
Console.WriteLine($"{threadName} waiting ...");
cancellationToken.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
At this point in history, new Thread is pretty much only useful for COM interop. In every other scenario, there are better solutions. In this case, you can send work to the thread pool by using Task.Run:
public static async Task Main(string[] args)
{
var cancellationTokenSource = new CancellationTokenSource();
var task1 = Task.Run(async () => await Run(cancellationTokenSource.Token, "threadName1", Method_FOO));
var task2 = Task.Run(async () => await Run(cancellationTokenSource.Token, "threadName2", Method_FOO));
await Task.WhenAll(task1, task2);
}
Thread don't wait task's end. When the 3 threads (main, thread1, thread2), the program is closed and running task killed.
You can make the method Run synchronous and manualy wait the task end, like :
public static class Program
{
public static async Task Main(string[] args)
{
var cancellationTokenSource = new CancellationTokenSource();
var thread1 = new Thread(() => Run(cancellationTokenSource.Token, "threadName1", Method_FOO));
var thread2 = new Thread(() => Run(cancellationTokenSource.Token, "threadName2", Method_FOO));
thread1.Start();
thread2.Start();
}
private static async Task Method_FOO(CancellationToken cancellationToken)
{
Console.WriteLine("It is called...");
await Task.Delay(300, cancellationToken);
Console.WriteLine("Worked ...");
}
private static void Run(CancellationToken cancellationToken, string threadName, Func<CancellationToken, Task> function)
{
try
{
while (true)
{
function(cancellationToken).Wait();
Console.WriteLine($"{threadName} waiting ...");
cancellationToken.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
Edit : Why not directly use the tasks?
public static void Main(string[] args)
{
var cancellationTokenSource = new CancellationTokenSource();
var task1 = Run(cancellationTokenSource.Token, "threadName1", Method_FOO);
var task2 = Run(cancellationTokenSource.Token, "threadName2", Method_FOO);
Task.Delay(TimeSpan.FromSeconds(5)).ContinueWith(t => cancellationTokenSource.Cancel());
Task.WaitAll(task1, task2);
}
public class test
{
public async Task Go()
{
await PrintAnswerToLife();
Console.WriteLine("done");
}
public async Task PrintAnswerToLife()
{
int answer = await GetAnswerToLife();
Console.WriteLine(answer);
}
public async Task<int> GetAnswerToLife()
{
await Task.Delay(5000);
int answer = 21 * 2;
return answer;
}
}
if I want to call Go in main() method, how can I do that?
I am trying out c# new features, I know i can hook the async method to a event and by triggering that event, async method can be called.
But what if I want to call it directly in main method? How can i do that?
I did something like
class Program
{
static void Main(string[] args)
{
test t = new test();
t.Go().GetAwaiter().OnCompleted(() =>
{
Console.WriteLine("finished");
});
Console.ReadKey();
}
}
But seems it's a dead lock and nothing is printed on the screen.
Your Main method can be simplified. For C# 7.1 and newer:
static async Task Main(string[] args)
{
test t = new test();
await t.Go();
Console.WriteLine("finished");
Console.ReadKey();
}
For earlier versions of C#:
static void Main(string[] args)
{
test t = new test();
t.Go().Wait();
Console.WriteLine("finished");
Console.ReadKey();
}
This is part of the beauty of the async keyword (and related functionality): the use and confusing nature of callbacks is greatly reduced or eliminated.
Instead of Wait, you're better off using
new test().Go().GetAwaiter().GetResult()
since this will avoid exceptions being wrapped into AggregateExceptions, so you can just surround your Go() method with a try catch(Exception ex) block as usual.
Since the release of C# v7.1 async main methods have become available to use which avoids the need for the workarounds in the answers already posted. The following signatures have been added:
public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);
This allows you to write your code like this:
static async Task Main(string[] args)
{
await DoSomethingAsync();
}
static async Task DoSomethingAsync()
{
//...
}
class Program
{
static void Main(string[] args)
{
test t = new test();
Task.Run(async () => await t.Go());
}
}
As long as you are accessing the result object from the returned task, there is no need to use GetAwaiter at all (Only in case you are accessing the result).
static async Task<String> sayHelloAsync(){
await Task.Delay(1000);
return "hello world";
}
static void main(string[] args){
var data = sayHelloAsync();
//implicitly waits for the result and makes synchronous call.
//no need for Console.ReadKey()
Console.Write(data.Result);
//synchronous call .. same as previous one
Console.Write(sayHelloAsync().GetAwaiter().GetResult());
}
if you want to wait for a task to be done and do some further processing:
sayHelloAsyn().GetAwaiter().OnCompleted(() => {
Console.Write("done" );
});
Console.ReadLine();
If you are interested in getting the results from sayHelloAsync and do further processing on it:
sayHelloAsync().ContinueWith(prev => {
//prev.Result should have "hello world"
Console.Write("done do further processing here .. here is the result from sayHelloAsync" + prev.Result);
});
Console.ReadLine();
One last simple way to wait for function:
static void main(string[] args){
sayHelloAsync().Wait();
Console.Read();
}
static async Task sayHelloAsync(){
await Task.Delay(1000);
Console.Write( "hello world");
}
public static void Main(string[] args)
{
var t = new test();
Task.Run(async () => { await t.Go();}).Wait();
}
Use .Wait()
static void Main(string[] args){
SomeTaskManager someTaskManager = new SomeTaskManager();
Task<List<String>> task = Task.Run(() => marginaleNotesGenerationTask.Execute());
task.Wait();
List<String> r = task.Result;
}
public class SomeTaskManager
{
public async Task<List<String>> Execute() {
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:4000/");
client.DefaultRequestHeaders.Accept.Clear();
HttpContent httpContent = new StringContent(jsonEnvellope, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage httpResponse = await client.PostAsync("", httpContent);
if (httpResponse.Content != null)
{
string responseContent = await httpResponse.Content.ReadAsStringAsync();
dynamic answer = JsonConvert.DeserializeObject(responseContent);
summaries = answer[0].ToObject<List<String>>();
}
}
}
try "Result" property
class Program
{
static void Main(string[] args)
{
test t = new test();
t.Go().Result;
Console.ReadKey();
}
}
C# 9 Top-level statements simplified things even more, now you don't even have to do anything extra to call async methods from your Main, you can just do this:
using System;
using System.Threading.Tasks;
await Task.Delay(1000);
Console.WriteLine("Hello World!");
For more information see What's new in C# 9.0, Top-level statements:
The top-level statements may contain async expressions. In that case, the synthesized entry point returns a Task, or Task<int>.
I'm writing WPF app and recently started working with await/async so the GUI thread does not perform any time consuming operations.
My problem is I want to load two collections from db asynchronously using Entity framework. I know I can't call two ToListAsync() methods on DbContext so I wanted to use tasks.
I wrote async method LoadData() that should wait on completing the LoadNotifications() and then call LoadCustomers().
But when the execution gets to await this.context.MailingDeliveryNotifications.ToListAsync(); it creates another task and somehow it doesn't care about the task.Wait() in my LoadData() method, so it calls LoadCustomers() before completing the first call on DbContext.
The code:
public async void LoadData()
{
Task task = this.LoadNotifications();
task.Wait();
await this.LoadCustomers();
}
private Task LoadNotifications()
{
return Task.Run(() => this.LoadNotificationsAsync());
}
private async void LoadNotificationsAsync()
{
List<MailingDeliveryNotification> res = await this.context.MailingDeliveryNotifications.ToListAsync();
this.Notifications = new ObservableCollection<MailingDeliveryNotification>(res);
}
private Task LoadCustomers()
{
return Task.Run(() => this.LoadNotificationsAsync());
}
private async void LoadCustomersAsync()
{
List<Customer> res = await this.context.Customers.ToListAsync();
this.Customers = new ObservableCollection<Customer>(res);
}
I know I can solve this using this code
public async void LoadData()
{
List<MailingDeliveryNotification> res = await this.context.MailingDeliveryNotifications.ToListAsync();
this.Notifications = new ObservableCollection<MailingDeliveryNotification>(res);
List<Customer> res2 = await this.context.Customers.ToListAsync();
this.Customers = new ObservableCollection<Customer>(res2);
}
but when I will need to add another collection to load from db, this method will grow to much. I want to keep my code Clean.
Simplify your code:
public async Task LoadDataAsync()
{
await LoadNotificationsAsync();
await LoadCustomersAsync();
}
private async Task LoadNotificationsAsync()
{
var res = await context.MailingDeliveryNotifications.ToListAsync();
Notifications = new ObservableCollection<MailingDeliveryNotification>(res);
}
private async Task LoadCustomersAsync()
{
var res = await context.Customers.ToListAsync();
Customers = new ObservableCollection<Customer>(res);
}
Or probably just:
public async Task LoadDataAsync()
{
Notifications = new ObservableCollection<MailingDeliveryNotification>(
await context.MailingDeliveryNotifications.ToListAsync());
Customers = new ObservableCollection<Customer>(
await context.Customers.ToListAsync());
}
I am trying to use Func with Async Method. And I am getting an error.
Cannot convert async lambda expression to delegate type 'Func<HttpResponseMesage>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<HttpResponseMesage>'.
below is my Code:
public async Task<HttpResponseMessage> CallAsyncMethod()
{
Console.WriteLine("Calling Youtube");
HttpClient client = new HttpClient();
var response = await client.GetAsync("https://www.youtube.com/watch?v=_OBlgSz8sSM");
Console.WriteLine("Got Response from youtube");
return response;
}
static void Main(string[] args)
{
Program p = new Program();
Task<HttpResponseMessage> myTask = p.CallAsyncMethod();
Func<HttpResponseMessage> myFun =async () => await myTask;
Console.ReadLine();
}
As the error says, async methods return Task,Task<T> or void. So to get this to work you can:
Func<Task<HttpResponseMessage>> myFun = async () => await myTask;
The path I usually take is to have the Main method invoke a Run() method that returns a Task, and .Wait() on the Task to complete.
class Program
{
public static async Task<HttpResponseMessage> CallAsyncMethod()
{
Console.WriteLine("Calling Youtube");
HttpClient client = new HttpClient();
var response = await client.GetAsync("https://www.youtube.com/watch?v=_OBlgSz8sSM");
Console.WriteLine("Got Response from youtube");
return response;
}
private static async Task Run()
{
HttpResponseMessage response = await CallAsyncMethod();
Console.ReadLine();
}
static void Main(string[] args)
{
Run().Wait();
}
}
This allows the rest of your Console app to run with full async/await support. Since there isn't any UI thread in a console app, you don't run the risk of deadlocking with the usage of .Wait().
Code fix such as:
static void Main(string[] args)
{
Program p = new Program();
Task<HttpResponseMessage> myTask = p.CallAsyncMethod();
Func<Task<HttpResponseMessage>> myFun = async () => await myTask;
Console.ReadLine();
}
Inside the Func run the task, wait for it and check for exception, then return the result.
Func<HttpResponseMessage> myFun = () =>
{
var t = Task.Run(async () => await myTask);
t.Wait();
if (t.IsFaulted)
throw t.Exception;
return t.Result;
};
I wonder how to accomplish the same thing the below program does without using extra threads or await and async keywords but only Tasks. A sample code would be awesome. It seems to me that we need to use TaskCompletionSource and Async versions of the IO-bound operations or any long-running operations.
static void Main(string[] args)
{
Task t = Go();
Console.WriteLine("Hello World");
Task.Delay(1000).GetAwaiter().OnCompleted(() => { Console.WriteLine("Completed"); });
Console.ReadLine();
}
static async Task Go()
{
var task = PrintAnswerToLife();
await task;
Console.WriteLine("Done");
}
static async Task PrintAnswerToLife()
{
var task = GetAnswerToLife();
int answer = await task;
Console.WriteLine(answer);
}
static async Task<int> GetAnswerToLife()
{
var task = Task.Delay(2000);
await task;
int answer = 21 * 2;
return answer;
}
You can do a pretty straightforward translation of async / await into Task by using ContinueWith. Other translations are also possible, e.g., Task.Delay becomes System.Threading.Timer.
The basic pattern is, for any async method that does an await:
static async Task Go()
{
var task = PrintAnswerToLife();
await task;
Console.WriteLine("Done");
}
becomes:
static Task Go()
{
var tcs = new TaskCompletionSource<object>();
var task = PrintAnswerToLife();
task.ContinueWith(_ =>
{
Console.WriteLine("Done");
tcs.SetResult(null);
});
return tcs.Task;
}
Correct error handling is a lot more work.