Why the console exits even after using await? - c#

using System;
using System.Threading;
using System.Threading.Tasks;
namespace application
{
public class Files
{
public static Task<string> runTask()
{
return Task.Run(() =>
{
Thread.Sleep(2000);
return "Hello World!";
});
}
public static async void Hello()
{
string result = await runTask();
Console.WriteLine(result);
Console.WriteLine("Execution Ended!");
}
public static void Main(string[] args)
{
Hello();
Console.WriteLine("The Async Code Is Running Above!");
}
};
};
The above C# code just prints "The Async Code Is Running Above!" and nothing happens after that.
How can I make this print things in following order (And where I'm going wrong):
"The Async Code Is Running Above!"
"Hello World!"
"Execution Ended!"
Thankyou!

There are a two main points in your question. First, don't use Thread.Sleep inside asynchronous methods, use Task.Delay instead. Second, you can make Main method async as well and return a Task to get an expected behavior (it's possible starting from C# 7.1)
public static Task<string> runTask()
{
return Task.Run(async () =>
{
await Task.Delay(2000);
return "Hello World!";
});
}
public static async Task Hello()
{
string result = await runTask();
Console.WriteLine(result);
Console.WriteLine("Execution Ended!");
}
static async Task Main()
{
await Hello();
Console.WriteLine("The Async Code Is Running Above!");
}

Avoid using void async methods, try returning tasks always. Check this post for more details async-await-when-to-return-a-task-vs-void
class Files
{
static void Main(string[] args)
{
Task t = Hello();
Console.WriteLine("The Async Code Is Running Above!");
//Wait for the task to complete
//Dont use this code in UI applications which will cause blocking
t.Wait();
//keep the application open
Console.ReadLine();
}
public static Task<string> runTask()
{
return Task.Run(async () =>
{
await Task.Delay(2000);
return "Hello World!";
});
}
public static async Task Hello()
{
string result = await runTask();
Console.WriteLine(result);
Console.WriteLine("Execution Ended!");
}
}

Related

.NET Core: Correct way of using async/await modifier in C# console application [duplicate]

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>.

Do nest await is the good way to run some async job intervally in parallel?

I have three different job class for different work, each of them needs to run in the background in a specified interval.
Is the following code is good in performance and clean in code style?
if not, how to fix it? I am new to c#, my dev environment is net core 3.1
class Program
{
static void Main(string[] args)
{
Method1();
Method2();
Console.ReadKey();
}
public static async Task Method1()
{
await Task.Run(() =>
{
var run = true;
for (run)
{
var c = await fetchConfigFromDBAsync()
run = c.run;
var interval = c.interval
await JobClass1.RunAsync()
Thread.Sleep(interval)
}
});
}
public static async Task Method2()
{
await Task.Run(() =>
{
for (true)
{
await JobClass2.RunAsync()
Thread.Sleep(new TimeSpan(0, 10, 4))
}
});
}
public static async Task Method3()
{
await Task.Run(() =>
{
for (true)
{
await JobClass3.RunAsync()
Thread.Sleep(new TimeSpan(1, 0, 3))
}
});
}
}
You must avoid Thread.Sleep for theses reasons. You can use Task.Delay() instead.
Then, you don't need to encapsulate your loops into Task.Run() if your async call is really an awaitable function, like sending data, commucicating with database, etc..
If your async function is more like heavy calculations, you can keep it. More explainations here.
And then, it's cleaner to wait all the infinites tasks rather than use Console.ReadLine()
static async Task Main(string[] args)
{
Task m1 = Method1();
Task m2 = Method2();
await Task.WhenAll(new[] { m1, m2 });
}
public static async Task Method2()
{
while (true)
{
await JobClass.RunAsync();
await Task.Delay(3);
}
}
public static async Task Method1()
{
while (true)
{
await JobClass.RunAsync();
await Task.Delay(3);
}
}

How to call on async Task function from Void class?

How to call on async Task function from Void class?
Let's say I got this built up like this,
I Want to call the methods in Run() in sync, but in the DoSomeStuffAsync and DoSomeStuffAsync 2
It requires await on some functions that has async awaitable functions.
My Question is, how can I in DoTask1 e.g. make the task to run sync? Like now the tasks just starts it and it doesn't wait until it finish at all.
static void Main(string[] args)
{
Run();
}
public void Run()
{
DoTask1();
DoTask2();
}
public void DoTask1()
{
var tasks = Task.Run(async () =>
{
await DoSomeStuffAsync();
await DoSomeStuffAsync2();
});
Task.WaitAll(tasks);
}
public void DoTask2()
{
var tasks = Task.Run(async () =>
{
await DoSomeStuffAsync();
await DoSomeStuffAsync2();
});
Task.WaitAll(tasks);
}
private async Task DoSomeStuffAsync(int daysBack)
{
try
{
var data= await GetData();
var objj = GenerateObjects();
await InsertToDb(objj ));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private async Task DoSomeStuffAsync2(int daysBack)
{
try
{
var data= await GetOtherData();
var objj = GenerateObjects();
await InsertToDb(objj ));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
The Console app static void Main() is calling on the Run() function.
You have a couple of options. For both of the options below, you should first make your Run method properly asynchronous (i.e., async Task).
If this is a .NET Core project, then option A is to make Main an async Task method. Then you can use async all the way.
If not, then you can have a single blocking call. I recommend that this go into your Main method, as such:
static void Main()
{
Run().GetAwaiter().GetResult();
}
Async void is a bad choice, generates compiler warnings, if an exception is uncaught there, your application is dead and you won’t probably have a proper call stack to debug with. But if you want, you already have the solution just
call directly the async task method. And wrappe it in a exception catcher
static void Main(string[] args)
{
Task callTask = Task.Run(() => Run());
callTask.Wait();
}
public async Task Run()
{
await DoSomeStuffAsync();
}

Task.WaitAll() hangs in console application

I have a console application in which I need to retrieve some data from 4 different sites. I placed each HTTP request in a task and I wait for them all to complete.
It was working when I only had to get data from 2 sites. but then I needed to add other sources of data and when adding 3 or more requests, the Task.WaitAll() hangs.
Below is my code.
The reason I ended up using Task.WaitAll() was because I need to stop and prevent the console application from exiting - i.e. I need to perform other tasks only after all the HTTP requests come back with data.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static Task[] tasks = new Task[3];
static void Main(string[] args)
{
try
{
Run();
}
catch (System.Exception ex)
{
}
}
public static async void Run()
{
//works when using one or two tasks
tasks[0] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
tasks[1] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
//fails when add 3 or more task
tasks[2] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
//tasks[3] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
Task.WaitAll(tasks);
var result4 = ((Task<Stream>)tasks[2]).Result;
}
}
public static class HttpExtensions
{
public static Stopwatch sw;
public static long http_ticks = 0;
public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
{
var taskComplete = new TaskCompletionSource<HttpWebResponse>();
request.BeginGetResponse(asyncResponse =>
{
try
{
HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
taskComplete.TrySetResult(someResponse);
}
catch (WebException webExc)
{
HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
taskComplete.TrySetResult(failedResponse);
}
}, request);
return taskComplete.Task;
}
public static async Task<Stream> GetMyData(string urlToCall)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToCall);
request.Method = HttpMethod.Get;
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
//using (var sr = new StreamReader(response.GetResponseStream()))
//{
return response.GetResponseStream();
//}
}
}
public static class HttpMethod
{
public static string Head { get { return "HEAD"; } }
public static string Post { get { return "POST"; } }
public static string Put { get { return "PUT"; } }
public static string Get { get { return "GET"; } }
public static string Delete { get { return "DELETE"; } }
public static string Trace { get { return "TRACE"; } }
public static string Options { get { return "OPTIONS"; } }
public static string Connect { get { return "CONNECT"; } }
public static string Patch { get { return "PATCH"; } }
}
}
There a number of concerns.
First, as I mentioned in the comments above, by not returning a Task you are more or less hanging your application since it can't tell when the Task is completed.
However, once you change the Run() method to return a task, you need to invoke it via a Task.Run call in your Main method.
Second, you are over-complicating your code by using WebClient. Switch to HttpClient and take advantage of its natural async/await API.
Third, you aren't actually awaiting anything in your Run() method so changing it to a task does nothing since you aren't awaiting a result which will cause it to run synchronously (no pun intended). Update your method to await a result.
Finally, WaitAll blocks the thread, which may not be what you want. You can use WhenAll instead and await that call, allowing your application to release the thread while your tasks run.
Below is a complete, working example of my recommended modifications, simplified to show a working program. The Main method recommendation is taken from https://social.msdn.microsoft.com/Forums/vstudio/en-US/fe9acdfc-66cd-4b43-9460-a8053ca51885/using-new-asyncawait-in-console-app?forum=netfxbcl
class Program
{
static Task[] tasks = new Task[3];
static HttpClient _client = new HttpClient();
static void Main(string[] args)
{
Console.WriteLine("Main start");
Task t = Run();
t.ContinueWith((str) =>
{
Console.WriteLine(str.Status.ToString());
Console.WriteLine("Main end");
});
t.Wait();
}
public static async Task Run()
{
tasks[0] = GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
tasks[1] = GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
tasks[2] = GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
await Task.WhenAll(tasks);
var result4 = (await (Task<Stream>)tasks[2]);
}
public static async Task<Stream> GetMyData(string urlToCall)
{
return await _client.GetStreamAsync(urlToCall);
}
}
I think the issue is more of understanding Task and async await; and I may be wrong so apologies up front.
Task is a managed thread that goes into a thread pool. Task has a Task.Result of Type T.
You can create a Task and then Start it and then Wait it. (Never a good idea to start and then immediately wait a task but for understanding...)
var task = new Task(() => DoWork());
task.Start();
task.Wait();
The task will perform the DoWork() method in a new thread.
The calling thread will BLOCK at task.Wait();
You can also give a Task a ContinueWith Action that will perform the remaining work on the calling thread.
var task = new Task(() => DoWorkOnNewThread());
task.ContinueWith(() => MainThreadWork());
task.Start(); //Notice no more task.Wait();
So, if you're following that little bit then you can sort of use async await correctly.
The async keyword tells the compiler to wrap all remaing code AFTER reaching the await keyword WHERE A GetAwaiter() is returned. This is important because until you actually create a task (preferably started also) and return it then you have no GetAwaiter();
private Task DoWorkAsync()
{
var task = new Task(() => DoWork());
task.Start();
return task;
}
private async void Method()
{
//Main thread code...
await DoWorkAsync(); //Returns to whoever called Method()
//More main thread code to be QUEUED to run AFTER DoWorkAsync is complete.
//This portion of code, when compiled, is essentially wrapped in the ContinueWith(...
}
So if you're still following along then here's the kicker. You're on the same thread UNTIL you return a GetAwaiter() which is only found in a Task. If the Task has never started then you'll await that Task forever technically. So here's some comments showing the thread transitions.
private Task DoWorkAsync()
{
Debug.WriteLine("Still on main thread")
var task = new Task(() =>
{
Debug.WriteLine("On background thread");
});
task.Start(); //On main thread.
return task; //On main thread.
}
private async void Method()
{
Debug.WriteLine("On main thread");
await DoWorkAsync(); //returns to caller after DoWorkAsync returns Task
Debug.WriteLine("Back on main thread"); //Works here after the task DoWorkAsync returned is complete
}
An easier way to return the task running is to return Task.Run(() => DoWork()); If you look at the return value of Run it is Task and that task has already been started.
Forgive me if this isn't what you wanted but I felt like there is more of a confusion about using async await correctly than there is confusion about your code. I may be wrong but I felt that if you could understand more about the Task itself and how async await works you would see your issue. If this isn't what you're looking for I'll delete the answer.

Await Task Not returning after completion

I'm having an issue where a task is completing, but not returning back. I have a website and a web service on different servers. The website makes a call to the web service which utilizes a library with function myFunction(). If I make a call to myFunction from a console app on the web service's server, it will return as expected. However, when I make the call from the website to the web service to call myFunction(), it will get to "Step 3", but not "Step 4". I have a simplified version of the calls below.
private string myFunction()
{
string myStr = myDoWork().GetAwaiter().GetResult();
return myStr;
}
private async Task<string> myDoWork()
{
logger.Debug("Step 1");
string answer = await aFunction();
logger.Debug("Step 4");
return answer;
}
public async Task<string> aFunction()
{
logger.Debug("Step 2");
return await bFunction(CancellationToken.None);
}
AsyncLock myLock = new AsyncLock();
public Task<string> bFunction(CancellationToken cToken)
{
return Task.Run(
async () =>
{
using (await myLock(cToken))
{
logger.Debug("Step 3");
result = "Hello";
return result;
}
},
cToken);
}
I'm new to async and await, so any help would be appreciated.
It's almost certainly a deadlock in myFunction(). Step 4 is scheduled to execute on the main thread, but it can't because the main thread is blocked waiting on GetResult().
It should be something closer to this:
private string myFunction()
{
// This is NOT good style - you should avoid blocking on the result of a task.
string myStr = Task.Run(async () => await myDoWork()).GetAwaiter().GetResult();
return myStr;
}
private async Task<string> myDoWork()
{
logger.Debug("Step 1");
string answer = await aFunction();
logger.Debug("Step 4");
return answer;
}
public Task<string> aFunction()
{
logger.Debug("Step 2");
return bFunction(CancellationToken.None);
}
AsyncLock myLock = new AsyncLock();
public async Task<string> bFunction(CancellationToken cToken)
{
using (await myLock(cToken))
{
logger.Debug("Step 3");
return "Hello";
}
}
In general, Task.Run() should be called from the highest level possible. Keep things as synchronous as possible and let the caller decide if they want to use a background thread.

Categories

Resources