I am learning task aysny based programing and cannot get to make this code work. The console prints the message only once and then disappears.
if I remove the read line and run the program(not debug mode) the console just appears with message saying press a key to continue. When I debug and put the debugger in console.write then it works fine for some time and then the console window disappears and restarts again. If I use for loop <10000 instead of while then also the behaviors is same
Could you please suggest what I am doing wrong.
static void Main(string[] args)
{
multitasker();
}
static async void multitasker()
{
Task task1 = new Task(PrintMessageA);
task1.Start();
await task1;
}
static void PrintMessageA()
{
while(true)
{
Console.WriteLine("Message from A");
Console.ReadLine();
}
}
Your main thread does not block and thus is exiting immediately. You would have to go "await all the way" in a sense and await multitasker as well, but you can't actually do that as seen later.
So first you return a task in multitasker
static async Task multitasker()
{
Task task1 = new Task(PrintMessageA);
task1.Start();
await task1;
}
The problem is you cannot make Main() (the entry point) async, so instead you would need to block that thread by instead calling Wait() on the returned Task
static void Main(string[] args)
{
multitasker().Wait();
}
Related
I want to pause the program so it does not close. I have a code running in the main thread. Tried this way, but this code instantly skips and the program closes instead of waiting.
How can I make it wait for the WaitMy method to complete?
static void Main(string[] args)
{
//any code here...
Console.WriteLine("Discovery started");
WaitMy();
}
private async static void WaitMy()
{
//await Task.Delay(30 * 1000);
await Task.Run(async () => await Task.Delay(30 * 1000));
}
The application runs with .net 4.5.
Change the code to following to make it work:
static async Task Main(string[] args)
{
//any code here...
Console.WriteLine("Discovery started");
await WaitMy();
}
How this works ?
You need C# 7.1 or later versions
Now Main method can be declared async and has return type as Task for introducing await
It will simply let the delay execute asynchronously, but will renter the main context for continuation, which will not exit
Another suggestion would be, you just need await Task.Delay(30 * 1000), wrapping inside the Task.Run is not required here
You are using Task Programming Library. What happens here is that, in your WaitMy method, you are scheduling a task to be executed (await Task.Run(...)). The task is being executed on a background thread.
In the meanwhile, the Main method continues its execution after the call to the WaitMy method.
The Main method ends right after, so the foreground thread is terminated, and all the background threads associated to its process are terminated too.
If you just want to perform a delay, just use:
System.Threading.Thread.Sleep(30 * 1000);
in the Main method, instead of calling WaitMy.
The method WaitMy can return a Task instance so you can have your main thread wait for it to be completed.
static void Main(string[] args)
{
//any code here...
Console.WriteLine("Discovery started");
var task = WaitMy();
task.Wait();
Console.WriteLine("And done :)");
}
private static Task WaitMy()
{
//await Task.Delay(30 * 1000);
return Task.Run(async () => await Task.Delay(30 * 1000));
}
If you just want the program to wait before terminating a simple answer would be to use
Console.ReadKey();
If you are curious why program terminates without waiting it is because you delegate waiting to ThreadPool by using Task.Run so waiting occurs on another thread an your application simply terminates before it can receive any result from ThreadPool
This question already has answers here:
Can't specify the 'async' modifier on the 'Main' method of a console app
(20 answers)
Closed 5 years ago.
I have this simple code:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Great. This compiles.
But let’s say I have a console application and I want to run the code above (calling SumTwoOperationsAsync()).
static void Main(string[] args)
{
SumTwoOperationsAsync();
}
But I've read that (when using sync) I have to sync all the way up and down:
Does this mean that my Main function should be marked as async?
Well, it can't be because there is a compilation error:
an entry point cannot be marked with the 'async' modifier
If I understand the async stuff , the thread will enter the Main function → SumTwoOperationsAsync → will call both functions and will be out. But until the SumTwoOperationsAsync
What am I missing?
In most project types, your async "up" and "down" will end at an async void event handler or returning a Task to your framework.
However, Console apps do not support this.
You can either just do a Wait on the returned task:
static void Main()
{
MainAsync().Wait();
// or, if you want to avoid exceptions being wrapped into AggregateException:
// MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
...
}
or you can use your own context like the one I wrote:
static void Main()
{
AsyncContext.Run(() => MainAsync());
}
static async Task MainAsync()
{
...
}
More information for async Console apps is on my blog.
Here is the simplest way to do this
static void Main(string[] args)
{
Task t = MainAsync(args);
t.Wait();
}
static async Task MainAsync(string[] args)
{
await ...
}
As a quick and very scoped solution:
Task.Result
Both Task.Result and Task.Wait won't allow to improving scalability when used with I/O, as they will cause the calling thread to stay blocked waiting for the I/O to end.
When you call .Result on an incomplete Task, the thread executing the method has to sit and wait for the task to complete, which blocks the thread from doing any other useful work in the meantime. This negates the benefit of the asynchronous nature of the task.
notasync
My solution. The JSONServer is a class I wrote for running an HttpListener server in a console window.
class Program
{
public static JSONServer srv = null;
static void Main(string[] args)
{
Console.WriteLine("NLPS Core Server");
srv = new JSONServer(100);
srv.Start();
InputLoopProcessor();
while(srv.IsRunning)
{
Thread.Sleep(250);
}
}
private static async Task InputLoopProcessor()
{
string line = "";
Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);
while(line != "quit")
{
Console.Write(": ");
line = Console.ReadLine().ToLower();
Console.WriteLine(line);
if(line == "?" || line == "help")
{
Console.WriteLine("Core NLPS Server Help");
Console.WriteLine(" ? or help: Show this help.");
Console.WriteLine(" quit: Stop the server.");
}
}
srv.Stop();
Console.WriteLine("Core Processor done at " + DateTime.Now);
}
}
I'm trying to get my head around await and async so I wrote this little test app, but what I expected does not happen.
Instead of waiting for the task to complete, the program continues to execute.
class Program
{
static void Main(string[] args)
{
var task = new Task(Run);
task.Start();
task.Wait();
Console.WriteLine("Main finished");
Console.ReadLine();
}
public async static void Run()
{
var task = Task.Factory.StartNew(() =>
{
Console.WriteLine("Starting");
Thread.Sleep(1000);
Console.WriteLine("End");
});
await task;
Console.WriteLine("Run finished");
}
}
Output
Main finished
Starting
End
Run finished
If I swap the 'await task' for 'task.Await()' it then runs as I would have expected producing
Starting
End
Run finished
Main finished
That is because when you have asynchronous void method, there is nothing you can do to track it's completion. Yours new Task(Run) only creates a task for starting the Run method. After the Run arrives at first await, there is nothing tracking the progress of the method, because there is nothing associated with the progress of the method. To fix it, you have to return Task instead of void and await that, instead of creating new Task.
Difference between async void and async Task is described here.
I am trying to use async and await and my problem is that it wont wait for the background process to finish. Maybe you are wondering why don't I just run the application synchronously?
I'm trying finish a part of my task ASAP and the rest can be awaited as shown in this example.
Thank you for the help guys! =)
class Program
{
static void Main(string[] args)
{
Run();
//Problem or Maybe Not? Needs this
//So that my application won't close immediately
Console.ReadLine();
}
private async static void Run()
{
Task<bool> TBool = ProcessRecords();
if (await TBool)
{
//Problem #1 This Line Doesn't Show
Console.WriteLine("End of Code");
//SHould be safe to close the application by Now
//But goes through here not waiting for the return
//of the last process.
Environment.Exit(0);
//My temporary solution is to indicate a Task.Delay(80000)
//to make sure that all the logging in the background
//are all done. I dont know if there is a function that shows
//that there are task running on the background or any
//other workaroung will help. =) thanks
}
}
private async static Task<bool> ProcessRecords()
{
Task newTask = null;
//Loop through all the records and send
//all the records to MQ ASAP
for (int x = 0; x < 10; x++)
{
//I wont wait for this Task so
//I can send the next record
newTask = SendToMQ(x);
}
//I only need to wait for the last Task to
//indicate that I can exit the system
//as soon as it finish
//Problem #2 The Console.WriteLine doesnt show the last record.
await newTask;
return true;
}
private async static Task SendToMQ(int count)
{
//actual sending of message (Important)
await Task.Delay(1000);
//Process of Logging Connect to DB etc, (Not so Important, but takes most of the time)
await LoggingRecord();
Console.Clear();
Console.WriteLine("Done Processing " + count.ToString() + " records");
}
//Logging of each record
private async static Task LoggingRecord()
{
await Task.Delay(5000);
//Problem #3 This Line Doesn't Show
Console.WriteLine("Last Log Finished");
}
}
You should use await whenever possible:
await Run();
However, in this case you cannot, so you must use Wait
static void Main(string[] args)
{
Run().Wait();
//Problem or Maybe Not? Needs this
//So that my application won't close immediately
//Console.ReadLine();
}
// note the return type is Task
private async static Task Run()
{
...
}
In ProcessRecords() you have the following line - I am not quite sure what you mean, so I didn't address it:
//Problem #2 The Console.WriteLine doesnt show the last record.
The above prints out
Done Processing 9 records
End of Code
Everything was working today until it stopped... Below is the minimum source code (I'm using VS 2012 Update 1, .Net 4.5). When I run it, app exits upon calling client.PostAsync() and so it never reaches Console.ReadLine(). Same in debugger, no exception, nothing, exit code 0.
I tried rebooting machine, restarting VS2012 - nothing works.
Again, everything was running today, not sure what changed (no software has been installed etc, all other network apps still work).
Any ideas? I think I'm loosing my mind.
class Program
{
static void Main(string[] args)
{
Run();
}
private async static void Run()
{
using (var client = new System.Net.Http.HttpClient())
{
var headers = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("submit.x", "48"),
new KeyValuePair<string, string>("submit.y", "15"),
new KeyValuePair<string, string>("submit", "login")
};
var content = new FormUrlEncodedContent(headers);
HttpResponseMessage response = await client.PostAsync("http://www.google.com/", content);
Console.ReadLine();
}
}
}
Your problem is that a program normally exits when its Main() method finishes. And your Main() finishes as soon as you hit the await in Run(), because that's how async methods work.
What you should do is to make Run() into an async Task method and then wait for the Task in your Main() method:
static void Main()
{
RunAsync().Wait();
}
private static async Task RunAsync()
{
…
}
In C# 7.1+ you should use async Main instead:
static async Task Main()
{
await RunAsync();
}
private static async Task RunAsync()
{
…
}
Few more notes:
You should never use async void methods, unless you have to (which is the case of async event handlers).
Mixing await and Wait() in a GUI application or in ASP.NET is dangerous, because it leads to deadlocks. But it's the right solution if you want to use async in a console application.